BZOJ 2342: SHOI2011 双倍回文
Posted lcf2000
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 2342: SHOI2011 双倍回文相关的知识,希望对你有一定的参考价值。
题目链接:双倍回文
回文自动机第二题。构出回文自动机,那么一个回文串是一个“双倍回文”,当且仅当代表这个串的节点\(u\)顺着\(fail\)指针往上跳,可以找到一个节点\(x\)满足\(2len_x=len_u\)。当然还需要\(len_u\)是\(4\)的倍数。
然后我们把\(fail\)树构出来,在上面\(dfs\)一遍就做完了。
下面贴代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) #define maxn 500010 using namespace std; typedef long long llg; char a[maxn]; int l[maxn],s[maxn][26],f[maxn]; int head[maxn],next[maxn],to[maxn]; int tt,la,ans,dt; bool w[maxn]; void add(int c,int n){ int p=la; while(a[n-l[p]-1]!=a[n]) p=f[p]; if(!s[p][c]){ int np=++tt,k=f[p]; l[np]=l[p]+2; while(a[n-l[k]-1]!=a[n]) k=f[k]; f[np]=s[k][c]; s[p][c]=np; } la=s[p][c]; } void link(int x,int y){to[++dt]=y;next[dt]=head[x];head[x]=dt;} void dfs(int u){ if(~l[u]&1) w[l[u]]=1; if(l[u]%4==0 && w[l[u]>>1]) ans=max(ans,l[u]); for(int i=head[u];i;i=next[i]) dfs(to[i]); w[l[u]]=0; } int main(){ File("a"); l[++tt]=-1; f[0]=1; int n;scanf("%d %s",&n,a+1); for(int i=1;i<=n;i++) add(a[i]-‘a‘,i); for(int i=tt;i>1;i--) link(f[i],i); dfs(1); dfs(0); printf("%d",ans); return 0; }
以上是关于BZOJ 2342: SHOI2011 双倍回文的主要内容,如果未能解决你的问题,请参考以下文章