BZOJ 2565 最长双回文串
题目链接:最长双回文串
回文自动机第三题。
正反各构一个回文自动机,就可以得到以每个位置开头和结尾的最长回文串了。
然后枚举一下断点就做完了。
下面贴代码:
#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 ans; struct PAM{ int l[maxn],s[maxn][26],f[maxn]; int tt,la,ans,dt,g[maxn]; PAM(){f[0]=1,l[++tt]=-1;} 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]; g[n]=l[la]; } }A,B; int main(){ File("a"); scanf("%s",a+1);int n=strlen(a+1); for(int i=1;i<=n;i++) A.add(a[i]-'a',i); reverse(a+1,a+n+1); for(int i=1;i<=n;i++) B.add(a[i]-'a',i); for(int i=1;i<n;i++) ans=max(ans,A.g[i]+B.g[n-i]); printf("%d",ans); return 0; }