2565: 最长双回文串
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2209 Solved: 1126
[ 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
直接manacher+DP
不过要注意aba答案应该是2,因为组成双回文字符串的两个字符串长度必须都大于0
还有这题n的范围有问题。。。。不止100000
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int p[1000010], L[1000010], R[1000010];
char s[500010], str[1000010];
int main(void)
{
int n, i, k, ans, mx, id;
while(scanf("%s", s)!=EOF)
{
n = strlen(s);
memset(str, '\0', sizeof(str));
str[0] = '$';
str[1] = '#';
for(i=0;i<=n-1;i++)
{
k = (i+1)*2;
str[k] = s[i];
str[k+1] = '#';
}
n = k+1;
s[n+1] = 0;
mx = ans = 0;
memset(L, 0, sizeof(L));
memset(R, 0, sizeof(R));
for(i=1;i<=n;i++)
{
p[i] = 1;
if(mx>i)
p[i] = min(p[2*id-i], mx-i+1);
while(str[i+p[i]]==str[i-p[i]])
p[i]++;
if(p[i]+i-1>mx)
{
mx = p[i]+i-1;
id = i;
}
R[i+p[i]-1] = max(R[i+p[i]-1], p[i]-1);
L[i-p[i]+1] = max(L[i-p[i]+1], p[i]-1);
}
for(i=1;i<=n;i++)
L[i] = max(L[i-1]-1, L[i]);
for(i=n;i>=1;i--)
R[i] = max(R[i+1]-1, R[i]);
for(i=3;i<=n-2;i+=2)
ans = max(ans, R[i]+L[i]);
printf("%d\n", ans);
}
return 0;
}