manacher

manacher(马拉车)算法是用于解决O(n)复杂度的情况下求字符串中最长回文串的长度。
首先,统一奇长度回文串和偶长度回文串的处理方式,可以在每两个字符中间插入"#",例如:$aba\Longrightarrow $ # \(a\) # \(b\) # \(a\) #。这样就可以把所有的回文串转化为奇长度回文串。设\(f[i]\)为回文串半径,对于奇长度回文串和偶长度回文串,设原长为\(n\),转换后的回文串长度为\(2n+1\)\(f[i]\times 2-1=2n+1\),所以\(n=f[i]-1\)
然后假设已知\(id+f[id]=mx\),求\(f[i]\),当\(i<mx\)时,即

\(f[i]=min(f[2\times id-i],mx-i)\)
否则\(f[i]=1\)
再看以i为中心的回文串是否能继续扩大。
最后找出最大值就可以了。
代码:

#include<iostream>
#include<cstring>
using namespace std;
int n;
char a[50000010];
int ans=1;
int f[50000010];
int main(){
	scanf("%s",a+1);
	n=strlen(a+1);
	for(int i=2*n;i>=1;i-=2){
		a[i]=a[i/2];
	}
	for(int i=1;i<=2*n+1;i+=2){
		a[i]='#';
	}
	int mx=0;
	int id=0;
	for(int i=1;i<=2*n+1;i++){
		if(mx>i){
			f[i]=min(f[id*2-i],mx-i);
		}
		else{
			f[i]=1;
		}
		while(a[i+f[i]]==a[i-f[i]]&&i+f[i]<2*n+2&&i-f[i]>0){
			f[i]++;
		}
		ans=max(ans,f[i]-1);
		if(i+f[i]>mx){
			mx=i+f[i];
			id=i;
		}
	}
	cout<<ans;
	return 0;
}
posted @ 2023-01-16 22:27  zzzzzz2  阅读(13)  评论(0编辑  收藏  举报