Manacher算法小记

一、算法简介

Manacher 算法能够在线性的时间内求出以每个位置为中心的最长回文半径。

首先将字符串所有字符(包括头尾)插入相同的分隔符,因为 Manacher 仅能找到长度为奇数的回文串,并在整个串前后方插入另两种分隔符防止越界。

定义位置 i回文半径为以 i 为对称中心的所有长度为奇数的回文串 S[l:r] 两端与 i 的距离 +1。显然,若 xi 的回文半径,则 S[ix+1:i+x1] 是回文串,且小于 x 的正整数均是 i 的回文半径。设 pi 表示 i最长回文半径

Manacher 算法记录在所有遍历过的位置 1i1 中,以任意一个点为回文中心的右端点的最大值 r,即 r=maxj=1i1{j+pj1}。设 d 为取到这个最大值的对称中心。

对于当前位置 i,若 i>r,则直接暴力求 pi。否则 ir,先将 i 赋值为 min(ri+1,p2di),再逐位扩展。为什么是这样?因为 i2di 关于 d 对称,所以在 [dpd+1,d+pd1] 范围内,以 2di 为对称中心的回文串也是以 i 为对称中心的回文串。若 p2di<ri+1,则 pi 最终就会等于 p2di,否则 p2di 还可以更大,矛盾。若 p2diri+1,则 pi 被初始化为 ri+1,使得每次扩展都会将 r 向右移动 1。故时间复杂度均摊线性。

P3805 【模板】manacher 代码如下

int main()
{
	scanf("%s",s+1);  n=strlen(s+1);
	t[0]='#';  t[++m]='@';
	for(int i=1; i<=n; i++)
		t[++m]=s[i],t[++m]='@';
	t[++m]='!';

	int d=0,r=0;
	for(int i=1; i<m; i++)
	{
		if(i>r)
			p[i]=1;
		else
			p[i]=min(r-i+1,p[2*d-i]);
		while(t[i-p[i]]==t[i+p[i]])
			p[i]++;
		if(i+p[i]-1>r)
			r=i+p[i]-1,d=i,cmax(ans,p[i]-1);
	}

	printf("%d\n",ans);
	
	return 0;
}

二、一些习题

P4555 [国家集训队] 最长双回文串

我的想法是枚举第一个串 X 的对称中心 i,查询所有 jpj+1i+pi1ji 能构成的串的最大值,树状数组维护即可,注意要判断两个串是否长度都大于 0

另一种做法是用 Manacher 预处理出以 i 为结尾/开头的最长回文串长度 xi,yi,答案即 max{xi+yi+1},时间复杂度线性 。

P1659 [国家集训队] 拉拉队排练

又被我写复杂了……

因为只要求奇数,我们只考虑以原串的点为中心的回文串的贡献,设当前点为 i,记 xi=pi/2,则它可以产生长度为 2×y1 的回文串,其中 y[1,xi]。我用线段树维护这个区间加的操作。但其实你直接差分一下,在 pi1 的位置单点加。最后统计答案的时候遇到长度为偶数的直接跳过即可,就不用再考虑除以 2 什么的了。

P6216 回文匹配

因为模拟赛考了这题发现我不会 Manacher 于是才有了这篇博客

要求回文串长度为奇数,容易想到用 Manacher 计算出以每个点为对称中心的回文串。再来计算 s2 的贡献。可以先用 KMP 跑出 s2s1 中出现的所有位置。

现在对于一个回文串 s1[l:r],设它的对称中心为 mid。假设 s1[i:j]=s2(lijr),则 s1[i:j] 对所有以 mid 为对称中心的回文串的贡献为 min(il+1,rj+1)。这个 min 很烦,于是我们直接主定 s2 的中心在 mid 左边,这样贡献就是 il+1 了。记 L 为满足 s2 对称中心在左边的 s2 最大左端点,直接将 l 打到区间 [l,L] 上,最后统计答案即可。对于 s2 中心等于 mid 或者在 mid 右边的同理。

差分一下时间复杂度线性。

P5446 [THUPC2018] 绿绿和串串

因为只要求长度在 |S| 以内的,所以第一次翻转的断点(即最后一个字符)一定在 S[1:n] 以内,其中 n=|s|

n 肯定是一种合法的方案。对于断点 i,若它的最长回文半径向右能到 n,那它肯定可以。若它的最长回文半径向左能到 1,那么只要向右到达的那个点可以那 i 也可以。时间复杂度线性。

posted @   xishanmeigao  阅读(17)  评论(0编辑  收藏  举报
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示