本来需要set,并查集等数据结构优化来着,被我暴力水过了。。。
双倍回文,反正肯定要跑一遍manacher
对于每一个#位置,在i-p【i】/2~i之间枚举找到一个最小的i,使得i+p【i】>i,就是说,在它左边属于回文范围内找到一个最长的回文,保证要挨着i,因为在i的回文p【i】范围内,所以右边和左边对称,光处理左边即可
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<set>
using namespace std;
int n=0,p[1200009];
char ch[500009],s[1200009];
void manacher()
{
int mx=0,id;
for (int i=1;i<n;i++)
{
if (mx>i)
p[i]=min(p[id-(i-id)],mx-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()
{
int len;
scanf("%d%s",&len,ch);
s[n++]='$';
for (int i=0;i<len;i++) s[n++]='#',s[n++]=ch[i];
s[n++]='#';
manacher();
int ans=0;
for (int i=1;i<n;i+=2)
{
int j=i-(p[i]/2);
if (!(j&1)) j++;
for (j;j<i;j+=2)
if(j+p[j]>i)
{
ans=max(ans,(i-j)*2);
break;
}
}
printf("%d",ans);
return 0;
}