首先用 manacher 处理一下。
然后我们可以枚举断点,问题变为求任意一个点为起点或终点的最长回文串,我们可以在 manacher 过程中更新这个值。
但这样做是不对的。因为我们只用了最长的回文串更新,未考虑一个点在大回文串内部的情况,所以我们可以考虑第二次递推,以 \(l\) 数组(起点最长)为例,递推式为 \(l_i=l_{i-2} -2\),即上一个字符开头的回文串减去最前和最后两个字符,\(r\) 数组同理。
为了避免重复计算断点的情况,我们只枚举占位符作为断点。另外注意特判两边是否都有回文串。
点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define debug cout<<"DEBUG"<<endl;
#define pb push_back
#define pii pair<int,int>
#define vi vector<int>
#define imp map<int,int>
using namespace std;
const int N=2e5+5;
int n,p[N<<1],l[N<<1],r[N<<1];
char c[N],s[N<<1];
int init(){
c[0]='^',c[1]='$';
int j=1;
for(int i=1;i<=n;i++){
c[++j]=s[i];
c[++j]='$';
}
c[++j]='%';
return j;
}
void manacher(){
int mr=1,mid=1;
for(int i=1;i<=n;i++){
if(i<mr) p[i]=min(mr-i,p[mid*2-i]);
else p[i]=1;
while(c[i+p[i]]==c[i-p[i]]) p[i]++;
if(i+p[i]>mr){
mr=i+p[i];
mid=i;
}
l[i-p[i]+1]=max(l[i-p[i]+1],p[i]-1);
r[i+p[i]-1]=max(r[i+p[i]-1],p[i]-1);
}
}
int main(){
cin>>s+1;
n=strlen(s+1);
n=init();
manacher();
for(int i=3;i<=n;i+=2){
l[i]=max(l[i],l[i-2]-2);
}
for(int i=n-2;i>=1;i-=2){
r[i]=max(r[i],r[i+2]-2);
}
int ans=0;
for(int i=1;i<=n;i+=2){
if(l[i]&&r[i]){
ans=max(ans,l[i]+r[i]);
}
}
cout<<ans<<"\n";
return 0;
}