思路:起初单纯的直接求解,是会超时的,后来知道有一种O(n)求最长回文子串的算法
点击打开链接,比较难理解的地方是p[i] = mx>i?min(p[2*idx-i],mx-i):1;,就像上文所说的,我们应该取两者中的最小者,一种情况是我们在之前的对称位置,也就是2*id-i,它能表示我们在i位置的最长子串,或者如果它的对称位置的最长回文子串大于我们的mx-i,那么在超出的部分我们不能保证它会和它的对称位置是一样的,因为已经超出了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 20000050;
char str[2*MAXN];
char s[MAXN];
int p[MAXN];
void Manacher(int *p,char *str,int len)
{
int mx = 0;
int idx = 0;
for (int i = 1; i < len; i++)
{
p[i] = mx>i?min(p[2*idx-i],mx-i):1;
while (str[i+p[i]] == str[i-p[i]])
p[i]++;
if (i + p[i] > mx)
{
mx = i + p[i];
idx = i;
}
}
}
int main()
{
while (scanf("%s",s) != EOF)
{
int nn = strlen(s);
int n = 2*nn+2;
str[0] = '$'; //担心数组越界
for (int i = 0; i <= nn; i++)
{
str[2*i+1] = '#';
str[2*i+2] = s[i];
}
Manacher(p,str,n);
int ans = 1;
for (int i = 0; i < n; i++)
ans = max(ans,p[i]);
printf("%d\n",ans-1);
}
return 0;
}