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
一行一个整数,表示最长双回文子串的长度。
Sample Input
baacaabbacabb
Sample Output
12
HINT
样例说明
从第二个字符开始的字符串aacaabbacabb可分为aacaa与bbacabb两部分,且两者都是回文串。
对于100%的数据,2≤|S|≤10^5
2015.4.25新加数据一组
Source
预处理以每一个#开头和结尾的最长回文串长度,枚举所有#再判断即可
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define M 1000010 5 using namespace std; 6 int n,ans; 7 int l[M],r[M],len[M]; 8 char s[M],a[M]; 9 void change() 10 { 11 s[0]=s[1]='#'; 12 for(int i=0;i<n;i++) 13 { 14 s[i*2+2]=a[i]; 15 s[i*2+3]='#'; 16 } 17 n=n*2+2; 18 s[n]=0; 19 } 20 void manacher() 21 { 22 int mx=0,mid; 23 for(int i=1;i<n;i++) 24 { 25 if(i<mx) len[i]=min(len[mid*2-i],mx-i); 26 else len[i]=1; 27 while(s[i-len[i]]==s[i+len[i]]) len[i]++; 28 if(mx<i+len[i]) 29 { 30 mx=i+len[i]; 31 mid=i; 32 } 33 r[i-len[i]+1]=max(r[i-len[i]+1],len[i]-1); 34 l[i+len[i]-1]=max(l[i+len[i]-1],len[i]-1); 35 } 36 } 37 int main() 38 { 39 scanf("%s",a); 40 n=strlen(a); 41 change(); 42 manacher(); 43 for(int i=1;i<n;i+=2) r[i]=max(r[i],r[i-2]-2); 44 for(int i=n-1;i>0;i-=2) l[i]=max(l[i],l[i+2]-2); 45 for(int i=1;i<n;i+=2) if(l[i]&&r[i]) ans=max(ans,l[i]+r[i]); 46 printf("%d",ans); 47 return 0; 48 }