Manacher算法讲解——字符串最长回文子串
引
入
引入
引入
Manachar算法主要是处理字符串中关于回文串的问题的,这没什么好说的。
M
a
n
a
c
h
e
r
算
法
Manacher算法
Manacher算法
朴素
求一个字符串中以每个点为中心的最长回文子串,这是
m
a
n
a
c
h
e
r
manacher
manacher 直接解决的问题。
以每个点为中心的回文子串是连续的,它并不像字符串的
b
o
r
d
e
r
border
border ,因此可以二分,于是在不知道
m
a
n
a
c
h
e
r
manacher
manacher 的情况下其实可以用字符串哈希+二分,只不过是
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn) 的。
但是
m
a
n
a
c
h
e
r
manacher
manacher 可以
O
(
n
)
O(n)
O(n) 算出,因此在有些专门卡
l
o
g
log
log 的题目中
m
a
n
a
c
h
e
r
manacher
manacher 有不可比拟的优越性。
我们不妨设以
i
i
i 为中心的最长回文子串长度为
F
[
i
]
∗
2
+
1
F[i]*2+1
F[i]∗2+1 ,
m
a
n
a
c
h
e
r
manacher
manacher 实际上是利用了一个回文字符串内的
F
[
]
F[]
F[] 的性质。
一个回文字符串,因为它是对称的,因此在仅考虑此字符串的情况下,它的
F
F
F 数组也是对称的,这便是
m
a
n
a
c
h
e
r
manacher
manacher 算法的核心了吧。
因此,我们考虑从左到右依次计算
F
[
i
]
F[i]
F[i] ,当遍历到一个点
i
i
i 时,首先
F
[
i
−
1
]
F[i-1]
F[i−1] 肯定已经算出来了。
如果
F
[
i
−
1
]
=
=
0
F[i-1]==0
F[i−1]==0 就直接暴力扩展 i ,否则,如果
F
[
i
−
2
]
<
F
[
i
−
1
]
−
1
F[i-2] < F[i-1]-1
F[i−2]<F[i−1]−1,说明什么呢?

F
[
i
]
=
F
[
i
−
2
]
F[i]=F[i-2]
F[i]=F[i−2],一定是这样的.
- F
[
i
]
F[i]
F[i] 肯定不能小于
F
[
i
−
2
]
F[i-2]
F[i−2] ,因为这个回文子串以
i
−
1
i-1
i−1 为对称中心,两边对称的两点,既然其中
i
−
2
i-2
i−2 可以扩大到
F
[
i
−
2
]
F[i-2]
F[i−2],且在
i
−
1
i-1
i−1 为中心的大回文串内 ,由于对称性,因此
[
i
−
F
[
i
−
2
]
,
i
+
F
[
i
−
2
]
]
[i-F[i-2],i+F[i-2]]
[i−F[i−2],i+F[i−2]] 范围内也一定是个回文串。
- F
[
i
]
F[i]
F[i] 也不能大于
F
[
i
−
2
]
F[i-2]
F[i−2] ,因为以每个点为中心的回文子串是连续的,
F
[
i
]
>
F
[
i
−
2
]
F[i]>F[i-2]
F[i]>F[i−2] 意味着
F
[
i
]
F[i]
F[i] 可以为
F
[
i
−
2
]
+
1
F[i-2]+1
F[i−2]+1,而由于
F
[
i
−
2
]
<
F
[
i
−
1
]
−
1
F[i-2] < F[i-1]-1
F[i−2]<F[i−1]−1 ,对于
i
−
2
i-2
i−2 来说,
F
[
i
−
2
]
+
1
F[i-2]+1
F[i−2]+1 仍然在大回文串范围内,因此
F
[
i
−
2
]
F[i-2]
F[i−2] 肯定就不止这个数了。
然后呢,是不是可以继续利用这个大红串呢?我们还可以考虑
F
[
i
−
3
]
F[i-3]
F[i−3] 是否小于
F
[
i
−
1
]
−
2
F[i-1]-2
F[i−1]−2 来决定
F
[
i
+
1
]
F[i+1]
F[i+1] ,考虑
F
[
i
−
4
]
F[i-4]
F[i−4] 是否小于
F
[
i
−
1
]
−
3
F[i-1]-3
F[i−1]−3 来决定
F
[
i
+
2
]
F[i+2]
F[i+2] ……直到超出红框或者:有一个
F
[
i
−
2
−
x
]
≥
F
[
i
−
1
]
−
1
−
x
F[i-2-x] ≥ F[i-1]-1-x
F[i−2−x]≥F[i−1]−1−x,这时候,
F
[
i
+
x
]
F[i+x]
F[i+x] 至少能扩大到红框边界吧,因为它的对称点都能扩大到红框边界。然后,再把
F
[
i
+
x
]
F[i+x]
F[i+x] 暴力往外扩。
我们会发现,整个过程中,每次往外扩一定能使前面所有的
i
+
F
[
i
]
i+F[i]
i+F[i] 的最大值变大,因此,它是线性的。
转化
很明显,对于一个回文字符串而言,并不一定中心是一个字符,也有可能是两个相同的字符的中界,即回文串长度为偶数,因此,一般把原串中每两个字符中间添一个没出现过的字符,于是所有的
F
[
i
]
∗
2
+
1
F[i]*2+1
F[i]∗2+1(包括边界的)都会变成
(
F
[
i
]
∗
2
+
1
)
∗
2
+
1
(F[i]*2+1)*2+1
(F[i]∗2+1)∗2+1 ,这样就可以解决长度为偶数的情况。
模板
void Manacher(char *s,int *F,int n) {// 已是转化后的 S
F[1] = 0;
for(int i = 2;i <= n;i ++) {
int j = i;
while(j < i-1+F[i-1] && j+F[i-1-(j-i+1)] < i-1+F[i-1]) F[j] = F[i-1-(j-i+1)],j ++;
F[j] = max(0,i-1+F[i-1] - j);
while(j+F[j] < n && j-F[j] > 1 && s[j+F[j]+1] == s[j-F[j]-1]) F[j] ++;
i = j;
}
return ;
}
Manacher算法讲解——字符串最长回文子串的更多相关文章
- manacher算法_求最长回文子串长度
很好的总结,转自: http://blog.csdn.net/dyx404514/article/details/42061017 总结为:两大情况,三小情况. 两大情况:I. i <= p 1 ...
- manacher算法学习(求最长回文子串长度)
Manacher总结 我的代码 学习:yyb luogu题目模板 xzy的模板 #include<iostream> #include<cstdlib> #include< ...
- [hdu 3068] Manacher算法O(n)最长回文子串
一个不错的讲解:https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/01.05.md # ...
- hihoCoder #1032 : 最长回文子串 [ Manacher算法--O(n)回文子串算法 ]
传送门 #1032 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相 ...
- Manacher算法:求解最长回文字符串,时间复杂度为O(N)
原文转载自:http://blog.csdn.net/yzl_rex/article/details/7908259 回文串定义:"回文串"是一个正读和反读都一样的字符串,比如&q ...
- Manacher (马拉车) 算法:解决最长回文子串的利器
最长回文子串 回文串就是原串和反转字符串相同的字符串.比如 aba,acca.前一个是奇数长度的回文串,后一个是偶数长度的回文串. 最长回文子串就是一个字符串的所有子串中,是回文串且长度最长的子串. ...
- 马拉车算法,mannacher查找最长回文子串
作用: 在线性时间内找到一个字符串的最大回文子串 原理: 奇偶变换:为处理字符串方便,现将给定的任意字符串进行处理,使所有可能的奇数/偶数长度的回文子串都转换成了奇数长度. 具体就是在每个字符的两边都 ...
- Manacher模板( 线性求最长回文子串 )
模板 #include<stdio.h> #include<string.h> #include<algorithm> #include<map> us ...
- Manacher算法--O(n)回文子串算法
转自:http://blog.csdn.net/ggggiqnypgjg/article/details/6645824 O(n)回文子串算法 注:转载的这篇文章,我发现下面那个源代码有点bug... ...
随机推荐
- systemctl设置程序开机启动、关闭、启用/禁用服务以vsftpd为例
参考:https://blog.csdn.net/qq_29663071/article/details/80814081 systemctl是RHEL 7 的服务管理工具中主要的工具,它融合之前se ...
- rpc的正确打开方式|读懂Go原生net/rpc包
前言 最近在阅读字节跳动开源RPC框架Kitex的源码,分析了如何借助命令行,由一个IDL文件,生成client和server的脚手架代码,也分析了Kitex的日志组件klog.当然Kitex还有许多 ...
- Elasticsearch学习系列二(基础操作)
本文将分为3块讲解Es的基础操作.分别为:索引(index).映射(mapping).文档(document). 索引操作 创建索引库 语法: PUT /索引名称{ "settings&qu ...
- 送分题,ArrayList 的扩容机制了解吗?
1. ArrayList 了解过吗?它是啥?有啥用? 众所周知,Java 集合框架拥有两大接口 Collection 和 Map,其中,Collection 麾下三生子 List.Set 和 Queu ...
- 5G的发布加快了智慧城市/三维物联网等行业的发展
最近很多人发现自己的5G手机突然没了5G信号,难道是美国搞的鬼? 不不不,这其实是因为5G的NSA基站被撤站了,官方已经做了部署,要大力推进SA网络建设.所以之前支持NSA模式的5G手机,现在都成了4 ...
- 关于个人全栈项目【臻美Chat】遇到的BUG以及解决方法
项目展示: 问题总结:一.单用户重复登录设备 将每次输入的用户名与已经记录在后台的数组ar比较,如果存在则表示重复. // 生成数组var ar="";socket.on('arr ...
- windows平台编译CEF支持H264(MP3、MP4)超详细
编译目标(如何确定目标定版本请查看:BranchesAndBuilding) CEF Branch:4664 CEF Commit:fe551e4 Chromium Version:96.0.4664 ...
- Three.js系列: 在元宇宙看电影,享受 VR 视觉盛宴
本文 gihtub 地址: https://github.com/hua1995116/Fly-Three.js 最近元宇宙的概念很火,并且受到疫情的影响,我们的出行总是受限,电影院也总是关门,但是在 ...
- C# 实例解释面向对象编程中的接口隔离原则
在面向对象编程中,SOLID 是五个设计原则的首字母缩写,旨在使软件设计更易于理解.灵活和可维护.这些原则是由美国软件工程师和讲师罗伯特·C·马丁(Robert Cecil Martin)提出的许多原 ...
- NewApiDay03_File类
File类创建一个新文件 File类的每一个实例可以表示硬盘(文件系统)中的一个文件或目录(实际上表示的是一个抽象路径) 使用File可以做到: 1:访问其表示的文件或目录的属性信息,例如:名字,大小 ...