题目大意:
输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。
题解:
若X,Y都是回文串且相邻,则共用一个’#‘。
可以对于每个‘#’找出其左边界和右边界。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 100050 char s0[N],s[2*N]; int l0,len; int p[2*N],l[2*N],r[2*N]; void manacher() { int mid=0,mx=0; for(int i=1;i<=len;i++) { if(i<=mx)p[i]=min(p[2*mid-i],mx-i+1); else p[i]=1; while(s[i+p[i]]==s[i-p[i]])p[i]++; l[i+p[i]-1]=max(p[i]-1,l[i+p[i]-1]); r[i-p[i]+1]=max(p[i]-1,r[i-p[i]+1]); if(i+p[i]-1>mx) { mid=i; mx=i+p[i]-1; } } } int main() { scanf("%s",s0+1); l0 = strlen(s0+1); s[0]='!'; for(int i=1;i<=l0;i++) { s[++len]='#'; s[++len]=s0[i]; } s[++len]='#'; s[++len]='@'; manacher(); for(int i=3;i<=len;i+=2) r[i]=max(r[i],r[i-2]-2); for(int i=len;i>=1;i-=2) l[i]=max(l[i],l[i+2]+2); int ans = 0; for(int i=1;i<=len;i+=2) ans=max(ans,r[i]+l[i]); printf("%d ",ans); return 0; }