专栏文章
Manacher,不知道怎么进入提高级大纲的老登
个人记录参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mingx7xf
- 此快照首次捕获于
- 2025/12/02 02:13 3 个月前
- 此快照最后确认于
- 2025/12/02 02:13 3 个月前
下文的所有字符串,下标默认从 开始。
在字符串的开头结尾,以及两字符之间,插入一个符号
#,比如 manacher 字符串就变为 #m#a#n#a#c#h#e#r#。这样做是为了让两种回文子串的情况(长度为奇、偶)归并为一种,减少分类讨论。Manacher 算法,可以在线性复杂度内,处理出 数组,其中 表示以下标 的字符为中心,最大的回文子串长度。
假设已经处理了 的值,需要求 的值,且已经知道了以位置 为中心,所有回文串的右端点的最大值为 ,其对应的回文中心为 。
对于求 ,分两种情况:
- ,这个时候已有条件无法处理,只能暴力扩展。
- ,图示如下:

这个时候,对 的情况继续讨论:
- 若 的回文区域在 内,但左端没到 :

显然,。
- 若 的回文区域的左端超过了 :

这个时候会发现,第 段与第 段相同,第 段与第 段相同。如果 可以扩展直至包含 段,则 段也相同,那么 段就相同。
但此时以 为中心的回文串没有扩展到 段,故矛盾,也就是这种情况不存在。
- 若 的回文区域的左端正好是 :

这个时候不好判断,暴力扩展即可。
该算法流程完毕,感性理解可以得出复杂度为线性。
代码
CPPcin>>str,s="#";
for (auto i:str)
s+=i,s+='#';
n=s.size(),s=' '+s;
fo(i,1,n){
if (i>r) p[i]=1;
else p[i]=min(r-i,p[2*t-i]);
while (i+p[i]<=n&&i-p[i]>=1&&s[i+p[i]]==s[i-p[i]])
p[i]++;
if (p[i]+i>r)
r=i+p[i],t=i;
mx=max(mx,p[i]-1);
}
图片出处:link。
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...