BZOJ2342: [Shoi2011]双倍回文
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2342
回文树然后我们把fail树建出来,然后对于0和1进行dfs就可以了。
#include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<vector> #include<cstring> #define rep(i,l,r) for (int i=l;i<=r;i++) #define down(i,l,r) for (int i=l;i>=r;i--) #define clr(x,y) memset(x,y,sizeof(x)) #define maxn 500500 #define eps 1e-6 using namespace std; struct data{int obj,pre; }e[maxn*2]; int ans,n,cnt,tot,cur,last,tot2; char ch[maxn]; int fail[maxn],s[maxn],to[maxn][30],len[maxn],b[maxn],head[maxn]; int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} return x*f; } void init(){ len[0]=0; len[1]=-1; fail[0]=1; tot=1; s[0]=-1; } void add(int c){ s[++n]=c; int cur,tmp,now; for (cur=last;s[n-len[cur]-1]!=s[n];cur=fail[cur]); if (!to[cur][c]){ len[++tot]=len[cur]+2; now=tot; for (tmp=fail[cur];s[n-len[tmp]-1]!=s[n];tmp=fail[tmp]); fail[now]=to[tmp][c]; to[cur][c]=now; } last=to[cur][c]; } void insert(int x,int y){ e[++tot2].obj=y; e[tot2].pre=head[x]; head[x]=tot2; } void dfs(int u){ if (len[u]>0&&len[u]%4==0&&b[len[u]/2]) ans=max(ans,len[u]); b[len[u]]=1; for (int j=head[u];j;j=e[j].pre){ int v=e[j].obj; dfs(v); } b[len[u]]=0; } int main(){ cnt=read(); scanf("%s",ch+1); init(); rep(i,1,cnt){ add(ch[i]-'a'+1); } rep(i,2,tot) insert(fail[i],i); dfs(0); dfs(1); printf("%d\n",ans); return 0; }