Description
顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为“abc”,逆序为“cba”,不相同)。
输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。
输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。
Input
一行由小写英文字母组成的字符串S。
Output
一行一个整数,表示最长双回文子串的长度。
正反各运行一次manacher,同时求出以某个位置为左/右边界的最长回文串长度,最后扫描一次每个分界点取最大值。
#include<cstdio> #include<cstring> char s[200010],s1[100010]; int p[200010],p2[200010]; int rx[200010]; int lx[200010]; inline int min(int a,int b){return a<b?a:b;} inline int maxs(int&a,int b){if(a<b)a=b;} int main(){ scanf("%s",s1); int l=strlen(s1); for(int i=0;i<l;i++)s[i+i+2]=s1[i]; l+=l; s[0]=1; s[l+1]=2; int mx=0,id=0; for(int i=2;i<=l;i++){ if(i<mx)p[i]=min(p[(id<<1)-i],mx-i); else p[i]=1; maxs(rx[i],1); while(s[i+p[i]]==s[i-p[i]]){ if(i+p[i]<=l)maxs(rx[i+p[i]],p[i]+1); ++p[i]; } if(i+p[i]>mx){ mx=i+p[i]; id=i; } } mx=id=l+1; for(int i=l;i>=2;i--){ if(i>mx)p2[i]=min(p2[(id<<1)-i],i-mx); else p2[i]=1; maxs(lx[i],1); while(s[i-p2[i]]==s[i+p2[i]]){ if(i-p2[i]>=2)maxs(lx[i-p2[i]],p2[i]+1); ++p2[i]; } if(i-p2[i]<mx){ mx=i-p2[i]; id=i; } } int ans=0; for(int i=3;i<l;i+=2)maxs(ans,lx[i+1]+rx[i-1]); printf("%d",ans); return 0; }