思路来自某一篇题解,manacher应该没错。
r[i]是一般大家定义的p[i],在计算r[i]时同时维护ll[i],rr[i],分别表示以i为终点/起点的最长回文子串。
更新是单向的。比如说rr[i]表示的是以i为起点的最长回文子串长度,那么就只能更新它右边的rr[i+2]。ll[i]同理。
大概是细节出错了……但是跟题解的代码对了,几乎一模一样的啊
WA了#12#13(两组hack数据吧)
若有人能告诉我我被hack在哪里,不胜感激!!!
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#ifdef TH
#define debug printf("Now is %d\n",__LINE__);
#else
#define debug
#endif
using namespace std;
template<class T>inline void read(T&x)
{
char ch=getchar();
int fu;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
x*=fu;
}
inline int read()
{
int x=0,fu=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*fu;
}
int G[55];
template<class T>inline void write(T x)
{
int g=0;
if(x<0) x=-x,putchar('-');
do{G[++g]=x%10;x/=10;}while(x);
for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
int n;
char ch[500010];
int r[500010],ll[500010],rr[500010];
int main()
{
ch[0]='$';
scanf("%s",ch+1);
n=strlen(ch+1);
// cout<<n<<endl;
for(int i=n;i>=1;i--)
{
ch[i*2]=ch[i];
ch[i*2+1]='#';
}
ch[1]='#';
ch[2*n+2]='@';
for(int i=1,mx=1,p=1;i<=2*n+1;i++)
{
r[i]=i<mx?min(mx-i,r[2*p-i]):1;
while(ch[i+r[i]]==ch[i-r[i]]) r[i]++;
if(mx<i+r[i])
{
mx=i+r[i];
p=i;
}
ll[i+r[i]-1]=max(ll[i+r[i]-1],r[i]-1);
rr[i-r[i]+1]=max(rr[i-r[i]+1],r[i]-1);
}
for(int i=1;i<=2*n+1;i+=2)
{
rr[i+2]=max(rr[i+2],rr[i]-2);
}
for(int i=2*n+1;i>=3;i-=2)
{
ll[i-2]=max(ll[i-2],ll[i]-2);
}
int ans=0;
for(int i=1;i<=2*n+1;i+=2)
{
ans=max(ans,ll[i]+rr[i]);
}
write(ans);
return 0;
}