【国家集训队】最长双回文串

foreverlasting

2018-07-08 20:09:01

Solution

回文自动机裸题。 分别建两个回文自动机,一个是正序,一个是倒序,然后通过自动机得出最长回文长度,接着枚举切割点就好了。 2018.12.15update:之前忘记考虑不切割的情况,那只要不枚举$n$为切割点就好了。 code: ``` //2018.11.21 by ljz #include<bits/stdc++.h> using namespace std; #define res register int #define LL long long #define inf 0x3f3f3f3f #define eps 1e-15 inline int read(){ res s=0; bool w=0; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=1;ch=getchar();} while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar(); return w?-s:s; } inline void _swap(res &x,res &y){ x^=y^=x^=y; } inline int _abs(const res &x){ return x>0?x:-x; } inline int _max(const res &x,const res &y){ return x>y?x:y; } inline int _min(const res &x,const res &y){ return x<y?x:y; } const int N=1e5+10; namespace MAIN{ int n; int a[N],b[N]; struct PAM{ struct Pam{ int vis[26],len,fail; }pam[N]; int las,cnt; PAM() {pam[1].fail=pam[0].fail=1,pam[cnt=1].len=-1;} inline void extend(const res &x,const res &id,char *str){ res p=las; for(;str[id-pam[p].len-1]!=str[id];p=pam[p].fail); if(!pam[p].vis[x]){ res np=++cnt,q=pam[p].fail; for(;str[id-pam[q].len-1]!=str[id];q=pam[q].fail); pam[np].fail=pam[q].vis[x],pam[p].vis[x]=np,pam[np].len=pam[p].len+2; } las=pam[p].vis[x]; } }A,B; char str[N]; int ans; inline void MAIN(){ scanf("%s",str+1); n=strlen(str+1); for(res i=1;i<=n;i++)A.extend(str[i]-'a',i,str),a[i]=A.pam[A.las].len; reverse(str+1,str+n+1); for(res i=1;i<=n;i++)B.extend(str[i]-'a',i,str),b[n-i+1]=B.pam[B.las].len; for(res i=1;i<n;i++)ans=_max(a[i]+b[i+1],ans); printf("%d\n",ans); } } int main(){ MAIN::MAIN(); return 0; } ```