[BZOJ2565]最长双回文串

Description

顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为“abc”,逆序为“cba”,不相同)。
输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分XY,(|X|,|Y|≥1)且XY都是回文串。

Input

一行由小写英文字母组成的字符串S

Output

一行一个整数,表示最长双回文子串的长度。

Sample Input

baacaabbacabb

Sample Output

12

HINT

样例说明

从第二个字符开始的字符串aacaabbacabb可分为aacaa与bbacabb两部分,且两者都是回文串。

对于100%的数据,2≤|S|≤10^5


2015.4.25新加数据一组

Source

2012国家集训队Round 1 day2

预处理以每一个#开头和结尾的最长回文串长度,枚举所有#再判断即可

代码:

 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 }

猜你喜欢

转载自www.cnblogs.com/Slrslr/p/9501503.html
今日推荐