Manacher 算法 1

\(Manacher\) 回文串利器当然不排除\(PAM\)这种玩意
压倒式的简单&\(O(n)\)的时间复杂度使得它胜出了

这玩意是求出以一个点为中心的最长回文串
拿一个已经知道的点去扩展右边界
记当前更新的点为\(i\),选点为\(now\)\(now\)为中心时最长回文串左右端点为\(l,r\)
对于\(i\)来说,关于\(now\)对称的点\(j\)的最长串已经更新完毕,记左右端点为\(jl,jr\)
这个时候由于\([l,r]\)之间是回文的,所以我们就知道\([i-(j-jl),i+(jr-j)]\)可能是一个回文串(需要更充分的条件)
但是我们知道\([l,j+(j-l)]\)是回文的,所以\([i-(j-l),i+(j-l)]\)是回文的
别的部分暴力\(check\)就好了
这一部分结束以后,当前答案由于中间插空答案会大\(1\)
然后再去一直更新就好了

由于回文串的性质,实际上求出了最长回文串就相当于求出了所有回文串,只不过是次级信息

对于奇偶回文串的处理就是中间插空直接搞
最后就是答案减1;

Code:

点击查看代码
void Manacher(){
	int m=2,len=strlen(ch+1);
	a[1]='$',a[2]='&';
	for(int i=1;i<+n;i++){
		m++;
		a[m]=ch[i];
		m++;
		a[m]='&';
	}
	for(int i=3,now=0,r=0;i<m;i++){
		if(i<r){
			q[i]=min(q[mid*2-i],r-i);
		}
		else{
			q[i]=1;
		}
		while(a[i-q[i]]==a[i+q[i]]){
			q[i]++;
		}
		if(i+q[i]>r){
			r=q[i]+i;
			mid=i;
		}
	}
}

两个校测的例题不方便放就扔文章题解区了

posted @ 2022-07-26 11:35  2K22  阅读(23)  评论(0)    收藏  举报