P4555 [国家集训队]最长双回文串
manacher
用manacher在处理时顺便把以某点开头/结尾的最长回文串的长度也处理掉。
然后枚举。
#include<iostream> #include<cstdio> #include<cstring> #include<cctype> using namespace std; template <typename T> inline T min(T &a,T &b) {return a<b ?a:b;} template <typename T> inline T max(T &a,T &b) {return a>b ?a:b;} char a[100005],b[200005]; int n,ans,p[200005],l1[200002],r1[200005]; int main(){ scanf("%s",a); int len=strlen(a); for(int i=0;i<len;++i) b[n++]='#',b[n++]=a[i]; b[n++]='#'; int mx=-1,id=0; for(int i=0;i<n;++i){ if(i<mx) p[i]=min(p[id*2-i],mx-i+1); else p[i]=1; while(i-p[i]>=0&&i+p[i]<n&&b[i-p[i]]==b[i+p[i]]) ++p[i]; if(i+p[i]-1>mx) mx=i+p[i]-1,id=i; l1[i-p[i]+1]=max(l1[i-p[i]+1],p[i]-1); r1[i+p[i]-1]=max(r1[i+p[i]-1],p[i]-1); //处理以某点开头/结尾的最长回文串的长度 } for(int i=2;i<n;i+=2) l1[i]=max(l1[i],l1[i-2]-2); //可能与前一点共用同个回文串更长
for(int i=n-3;i>=0;i-=2) r1[i]=max(r1[i],r1[i+2]-2); for(int i=0;i<n;i+=2) ans=max(ans,l1[i]+r1[i]); printf("%d",ans); return 0; }