BZOJ 2342: [Shoi2011]双倍回文
2342: [Shoi2011]双倍回文
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3286 Solved: 1247
[Submit][Status][Discuss]
Description
Input
输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容。
Output
输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文子串不存在,则输出0。
Sample Input
16
ggabaabaabaaball
ggabaabaabaaball
Sample Output
12
HINT
N<=500000
题解:
Manacher+枚举
代码:
#include<iostream> #include<cstring> #include<cstdio> #define maxn 500009 using namespace std; char s[maxn*2],str[maxn*2]; int Len[maxn*2],len,n; void getstr(){ int k=0;str[k++]='$'; for(int i=0;i<len;i++){ str[k++]='#';str[k++]=s[i]; } str[k++]='#';len=k; } void Manacher(){ getstr();int mx=0,id; for(int i=1;i<len;i++){ if(mx>i)Len[i]=min(Len[2*id-i],mx-i); else Len[i]=1; while(str[i+Len[i]]==str[i-Len[i]]) Len[i]++; if(Len[i]+i>mx)mx=Len[i]+i,id=i; } } int main(){ scanf("%d",&n); scanf("%s",&s);len=n; Manacher();int ans=0; for(int i=1;i<=len;i++){ if(str[i]=='#'&&Len[i]>ans+1) for(int j=((Len[i]-1)/4)*2;j>ans/2;j-=2){ if(Len[i+j]>=j&&Len[i-j]>=j){ ans=max(ans,j*2);break; } } } printf("%d\n",ans); return 0; }