最长回文子串(Manacher算法)
来源:互联网 发布:机顶盒的电视直播软件 编辑:程序博客网 时间:2024/06/08 17:36
本总结是是个人为防止遗忘而作,不得转载和商用。
题目
给定字符串str,若子串s是回文串,称s为str的回文子串。设计算法,计算str的最长回文子串。
Manacher算法
因为回文串有奇数和偶数的不同。判断一个串是否是回文串,往往要分开编写,造成代码的拖沓。
为了解决这个问题,就采用下面的做法:
因此长度为n的字符串,共有n-1个“空”(gap),如:字符串abc,a和b之间有个“空”,b和c之间有个“空”,如果用“#”表示“空”的话,那字符串就可以写成:a#b#c
而如果在把首字母前面和末字符后面的“空”也算上的话,那字符串和“空”一起就一共有2n+1个,必定是奇数。
这里将类似:#a#b#c#的串称作gap串。
因此,将待计算母串扩展成gap串,计算回文子串的过程中,只考虑奇数匹配即可。
最后,为了处理统一,在最前面假设一个字符串中未出线的字符,如$,并用一个数组P[i]记录以字符S[i]为中心的最长回文子串向左/右扩张的长度(包括S[i]),比如S和P的对应关系,如下:
字符串 :12212321 -> S[]= “$ # 1 # 2 # 2 # 1 # 2 # 3 # 2 # 1 #”
字符串和P[i]:
S[]= # 1 # 2 # 2 # 1 # 2 # 3 # 2 # 1 #
P[] = 1 2 1 2 5 2 1 4 1 2 1 6 1 2 1 2 1
对于S[i=8] = 1,其回文最长向左4个向右4个(包括自己),所以将P[8] = 4。
又因为P[i] - 1正好是原字符串中回文串的总长度,所以之后只需要遍历遍历P,并找到最大的就可以了。
Tip:
因为P中当i为奇数时对应的S都是#,所以只需要计算P[i]为偶数的情况。
下面求P[i] 。
PS:假设P[0 … i-1]已经算出来,现在想求P[i]。
如上图所示。
对于:
S[]= # 1 # 2 # 2 # 1 # 2 # 3 # 2 # 1 #
P[]= 1 2 1 2 5 2 1 4 1 2 1 6 1 2 1 2 1
因为S[i + P[i]]正好是“以i为中心的回文子串的下一个字符”,即:S[i+P[i]] 的前一个字符还属于S[i] 的回文子串,所以i+P[i]就很重要。
又因为P[0 … i-1]都已经算出来了,所以我们就可以找到S[0]~S[i-1] 的i+P[i] 的最大值,这里将其记做mx。
假设mx = id+P[id]。
为了知道以id为中心的回文子串,这里我们记mx关于id的对称位置是my,同理i关于id的对称点是j。
话说,我们已经算出了P[0]~ P[i-1],再加上i和j在以id为中心的回文子串范围内,所以P[i] = P[j]。
而如果以j为中心的回文子串左侧超过my,则至少我知道“以j为中心左到my长度,右同样长度的回文子串”和“以i为中心的左右同样长度的回文子串”的长度是相等的,所以先将p[j] 赋值成j-my,至于剩下的部分,单独算就好。
综上:
如果p[j] > j- my:则P[i] = j - my = mx - i
如果P[j] < j- my:则P[i] = P[j] = P[2*id - i]
于是:
P[i] = min(P[2*id - i], mx - i)
注意:上面的公式的前提是i<mx,如果i>mx,则只能把P[i]初始化为1了。
写成代码的话就是:
if(mx > i ) {
P[i]= min(P[2*id - i], mx - i);
}else {
P[i]= 1;
}
然后看看在此基础上以S[i]为中心的回文串能不能在扩展扩展,于是再添加一行代码:
for(;S[i+P[i]] == S[i-P[i]]; P[i]++);
上面就算出了以S[i]为中心的回文子串,接下来:
如果mx <i+P[i]:
就更新mx,即mx = i +P[i]
并令id = i
然后不停的做上面的事情,将i从头遍历到尾,就OK了。
哦,对了,补充下初始化的值:
P[0]= 1, id = 0, mx = 1
时间复杂度
O(N)
- Manacher算法求最长回文子串
- Manacher算法求最长回文子串
- 最长回文子串(Manacher算法)
- Manacher算法 最长回文子串
- 最长回文子串的manacher算法
- 最长回文子串,Manacher算法
- Poj3974 最长回文子串 Manacher算法
- 最长回文子串 manacher算法
- Manacher算法(最长子回文串)
- hihocoder1032(最长回文子串manacher算法)
- HDU3068(最长回文子串manacher算法)
- 最长回文子串 用manacher算法
- hiho1032 : 最长回文子串 Manacher算法
- 最长回文子串 - Manacher算法
- 最长回文子串Manacher算法
- Manacher算法 - 最长回文子串
- manacher算法-最长子回文串
- 最长回文子串-Manacher算法
- Android onActivityResult不执行
- 涂涂乐的详细实现之四--unity3d调用EmguCV实现图片识别
- Apache Kylin资料收集整理
- js事件委托机制
- 第一篇个人博客,仅为记录学习的历程,点点滴滴。
- 最长回文子串(Manacher算法)
- Ubuntu16.04安装jdk1.8
- Maven打包时报Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.2:war解决方案
- 最近做小四轴的一些问题
- windows下MatConvNet深度学习框架的搭建
- AngularJS 动画
- 基本线程同步
- cesium原理篇(二)--网格划分
- CSS基础学生11-CSS用z-index进行层次堆叠