版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/FZHvampire/article/details/51721188
2342: [Shoi2011]双倍回文
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 1855 Solved: 691
[Submit][Status][Discuss]
Description
Input
输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容。
Output
输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文子串不存在,则输出0。
Sample Input
16
ggabaabaabaaball
Sample Output
12
HINT
N<=500000
先用
然后暴力枚举中心位置,用之前
虽然是暴力,但是跑的飞快。。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1000010;
int n,p[N<<1];
char s[N],ch[N];
inline void manacher(){
int maxn=1,id=1,i;
for(ch[0]='$',ch[1]='#',i=1;i<=n;++i)
ch[i<<1]=s[i-1],ch[i<<1|1]='#';
for(i=1;i<=(n<<1|1);++i){
p[i]=min(maxn-i,p[id*2-i]);
while(ch[i+p[i]]==ch[i-p[i]]) ++p[i];
if(maxn<p[i]+i) maxn=p[i]+i,id=i;
}
}
int main(){
int i,ans=0;
scanf("%d%s",&n,s);
manacher();
for(i=1;i<=(n<<1|1);i+=2){
int now=p[i],o=i+p[i]-1;
if(ans>=o-i) continue;
while(o>=i){
if(((o-i)/2)%2==0){
int oo=(o+i)/2;
if(p[oo]+oo-1>=o){
ans=max(ans,o-i);
break;
}
}
o-=2;
}
}
printf("%d\n",ans);
}