版权声明:请大家斧正,如喜欢的话,为拙见点一个赞吧。 https://blog.csdn.net/qq_39897867/article/details/86776719
题目
https://www.luogu.org/problemnew/show/P4555
解题思路
在朴素的马拉车基础上求出 和 数组,以i为结尾的最长回文子串的长度ll[i],和以i为开头的最长回文子串的长度rr[i]。
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#define rep(i,x,y) for(register int i=x;i<=y;++i)
using namespace std;
const int maxn=300010;
char s[maxn<<1],a[maxn];
int l[maxn<<1],r[maxn<<1],hw[maxn],n,ans=0,now,ll[maxn<<1],rr[maxn<<1];
void change(){
rep(i,0,n-1) s[(i<<1)+2]=a[i],s[(i<<1)+3]='#';
s[0]=s[1]='#'; n=(n<<1)+2; s[n]=0;
}
void manacher(){
int maxright=0,mid;
rep(i,1,n-1) {
hw[i]=(i<maxright)?min(hw[(mid<<1)-i],hw[mid]+mid-i):1;
while (s[i+hw[i]]==s[i-hw[i]]) hw[i]++;
if (hw[i]+i>maxright) maxright=hw[i]+i,mid=i;
ll[i+hw[i]-1]=max(ll[i+hw[i]-1],hw[i]-1);
rr[i-hw[i]+1]=max(rr[i-hw[i]+1],hw[i]-1);
}
}
int main(){
// freopen("data.in","r",stdin);freopen("1.out","w",stdout);
scanf("%s",a); n=strlen(a);
change(),manacher();
for(register int i=1;i<=n;i+=2) rr[i]=max(rr[i],rr[i-2]-2);
for(register int i=n;i>=1;i-=2) ll[i]=max(ll[i],ll[i+2]-2);
for(register int i=1;i<=n;i+=2) if (rr[i]&&ll[i]) ans=max(ans,ll[i]+rr[i]);
printf("%d",ans);
}