2565: 最长双回文串
Time Limit: 10 Sec Memory Limit: 128 MB[ Submit][ Status][ Discuss]
Description
顺序和逆序读起来完全一样的串叫做回文串。比如
acbca
是回文串,而
abc
不是(
abc
的顺序为
“abc”
,逆序为
“cba”
,不相同)。
输入长度为 n 的串 S ,求 S 的最长双回文子串 T, 即可将 T 分为两部分 X , Y ,( |X|,|Y|≥1 )且 X 和 Y 都是回文串。
输入长度为 n 的串 S ,求 S 的最长双回文子串 T, 即可将 T 分为两部分 X , Y ,( |X|,|Y|≥1 )且 X 和 Y 都是回文串。
Input
一行由小写英文字母组成的字符串S。
Output
一行一个整数,表示最长双回文子串的长度。
Sample Input
baacaabbacabb
Sample Output
12
HINT
样例说明
从第二个字符开始的字符串aacaabbacabb可分为aacaa与bbacabb两部分,且两者都是回文串。
对于100%的数据,2≤|S|≤10^5
2015.4.25新加数据一组
Source
上道题根本做不起,这道题才想到
正向for一遍,反向for一遍,求以该点为端点的最大值
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 500000 + 5;
char a[N], s[N];
int p[N], l[N], r[N], n, lena, mx, now, ans, id;
void manacher(){
for( int i = 1; i <= n; i++ ){
if( i < mx ) { p[i] = min(mx-i,p[2*id-i]); }
else p[i] = 1;
while( s[i+p[i]] == s[i-p[i]] ) p[i]++;
if( i + p[i] > mx ){
id = i; mx = i + p[i];
}
}
}
int main(){
scanf("%s", a); lena = strlen(a); s[0] = '*';
for( int i = 0; i < lena; i++ ) { s[++n] = a[i]; s[++n] = '#'; } s[++n] = '#';
manacher(); now = 1;
for( int i = 1; i <= n; i++ )
if( s[i] == '#' ){
while( now + p[now] < i ) now++;
l[i] = i-now;
} now = n;
for( int i = n; i >= 1; i-- )
if( s[i] == '#' ){
while( now - p[now] > i ) now--;
r[i] = now-i;
}
for( int i = 1; i <= n; i++ ) ans = max(ans,l[i]+r[i]);
printf("%d", ans);
return 0;
}