引言
文章相关代码已收录至我的github,欢迎star:lsylulu/myarticle
有这样一个问题,给定一个字符串,返回最长回文的子串的长度?要求时间复杂度为O(n)。
正常情况下我们会这么做,先将字符串进行特殊处理比如11311处理成#1#1#3#1#1#,然后遍历每个索引,找最长回文数。结果/2为正确答案。
那么,如何找每个索引的最长回文数呢?
通常情况下是设置一个start和end变量,start向右走,end向左走,每走一步比较start与end指向的元素是否相等,并且注意一下越界情况。start-end便是回文长度。但是,这种算法的时间复杂度为O(n^2)。能不能设计一个T=O(n)的算法呢?答案是Manacher算法。
文章导读
- Manacher基本概念
- Manacher执行流程
- Manacher对应的代码实现
- 对Manacher的思考
- Manacher扩展
- 总结
一、Manacher的基本概念
R--记录回文最右边界。随着字符数组的遍历,R的值必然不会减小,要么与上一次相等,要么被推向右边。
来看一个例子助于理解:
a b d b a b d b a
0 1 2 3 4 5 6 7 8
刚开始,R的值默认是-1。随着数组的遍历,R的值将做如下变化。R=-1->0->1->4->4->8->8->8->8->8
C--回文中心。C与R是相辅相成的,C是R对应的回文中心,R一旦改变,C也会跟着变化。刚开始,C的值默认也是-1。继续上个例子C的值将做如下变化。C=-1->0->1->2->2->4->4->4->4->4
curArr[ ]--长度与给定字符串相同(准确来说是'#'处理后的字符串)记录每一个索引的最大回文长度。
i--当前遍历的索引。
i’--i关于C的对称点。
二、Manacher算法的执行流程
对于每一个索引,都有相应的C和R。我们所要做的就是知道该索引后,给出currArr[i]的粗略值,根据这个粗略值将currArr[i]精确计算。再完善C与R的值。
每一次的遍历,大致分为两种情况:
1&#x