BZOJ2565: 最长双回文串(回文树)
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2565
记录一下每个点往前最长延伸位置,正反两遍,枚举分割点。
#include<cstring> #include<iostream> #include<algorithm> #include<cstdio> #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 ll long long #define maxn 100500 using namespace std; int len[maxn],cnt[maxn],p1[maxn],p2[maxn],fail[maxn],s[maxn],to[maxn][30]; int n,ans,tot,last,L,len1,len2; char ch1[maxn],ch2[maxn]; void init(){ len[tot=0]=0; len[++tot]=-1; fail[0]=1; s[n=0]=-1; last=0; clr(to,0); } void add(int c,int p[]){ s[++n]=c; int tmp,cur,now; for (cur=last;s[n-len[cur]-1]!=c;cur=fail[cur]); if (!to[cur][c]){ len[++tot]=len[cur]+2; now=tot; for (tmp=fail[cur];s[n-len[tmp]-1]!=c;tmp=fail[tmp]); fail[now]=to[tmp][c]; to[cur][c]=now; } last=to[cur][c]; cnt[last]++; p[n]=n-len[last]+1; } int main(){ scanf("%s",ch1); L=strlen(ch1); rep(i,0,L-1) ch2[L-1-i]=ch1[i]; init(); rep(i,0,L-1) add(ch1[i]-'a',p1); init(); rep(i,0,L-1) add(ch2[i]-'a',p2); rep(i,0,L-1){ len1=i-p1[i]+1; len2=L-i-p2[L-i]+1; ans=max(ans,len1+len2); } printf("%d\n",ans); return 0; }