2342: [Shoi2011]双倍回文
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2734 Solved: 1051
[ Submit][ Status][ Discuss]
Description
Input
输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容。
Output
输出文件只有一行,即:输入数据中字符串的最长双倍回文子串的长度,如果双倍回文子串不存在,则输出0。
Sample Input
16
ggabaabaabaaball
ggabaabaabaaball
Sample Output
12
HINT
N<=500000
Source
蒟蒻表示第一次写manacher都写不来
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<set>
using namespace std;
const int N = 500000 + 5;
int n,ans,q[N],p[N];
char ch[N];
set<int> t;
bool cmp( int a, int b ){
return (a-p[a]) < (b-p[b]);
}
void manacher(){
int mx = 0, id;
for( int i = 1; i <= n; i++ ){
if( mx > i ) p[i] = min(mx-i,p[2*id-i]);
else p[i] = 0;
for( ; ch[i-p[i]] == ch[i+p[i]+1] ; p[i]++ );
if( p[i] + i > mx ) id = i, mx = p[i] + i;
}
}
int main(){
scanf("%d%s", &n, ch+1);
manacher();
for( int i = 1; i <= n; i++ ) q[i] = i;
std::sort(q+1,q+n+1,cmp); int now = 1;
for( int i = 1; i <= n; i++ ){
while( now <= n && q[now]-p[q[now]] <= i ){
t.insert(q[now]); now++;
}
set<int>::iterator tmp = t.upper_bound(i+p[i]/2);
if( tmp != t.begin() ) ans = max(ans,(*--tmp-i)*4);
}
printf("%d",ans);
return 0;
}