[洛谷4555] [国家集训队]最长双回文串 {Manacher算法}

版权声明:请大家斧正,如喜欢的话,为拙见点一个赞吧。 https://blog.csdn.net/qq_39897867/article/details/86776719

题目

https://www.luogu.org/problemnew/show/P4555


解题思路

在朴素的马拉车基础上求出 l l ll r r rr 数组,以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); 
}


猜你喜欢

转载自blog.csdn.net/qq_39897867/article/details/86776719