BZOJ2342:[SHOI2011]双倍回文(Manacher)

Description

 

Input

输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容。

Output

输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文子串不存在,则输出0

Sample Input

16
ggabaabaabaaball

Sample Output

12

HINT

N<=500000

Solution

假设manacher过程中求到了位置i
那么我们从i位置一步一步往左右扩张求len[i]的时候
扩张过程中经历的串一定是回文串,只需要判断这些串的左半边是否回文然后更新答案即可。

Code

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #define N (1000000+1000)
 5 using namespace std;
 6 
 7 int n,tot,len[N];
 8 char a[N],s[N];
 9 
10 void Manacher()
11 {
12     int x,mid=0,maxn=0,ans=0;
13     for (int i=1; i<=tot; ++i)
14     {
15         if (i>maxn) x=1;
16         else x=min(maxn-i+1,len[mid*2-i]);
17         while (s[i+x]==s[i-x])
18         {
19             ++x;
20             if (s[i]=='#' && x%4==1 && len[i-x/2]>=x/2)
21                 ans=max(ans,x-1);
22         }
23         len[i]=x;
24         if (i+x-1>maxn) maxn=i+x-1,mid=i;
25     }
26     printf("%d",ans);
27 }
28 
29 int main()
30 {
31     scanf("%d%s",&n,a);
32     
33     s[++tot]='@'; s[++tot]='#';
34     for (int i=0; i<n; ++i)
35         s[++tot]=a[i], s[++tot]='#';
36     s[++tot]='$';
37     Manacher();
38 }
posted @ 2018-08-08 21:15  Refun  阅读(189)  评论(0编辑  收藏  举报