可以去https://segmentfault.com/a/1190000003914228看原版,但是有些方面感觉我解释的要更多一些,同时改正了一处错误。
问题定义:
最长回文串问题:给定一个字符串,求出它的最长回文串长度。
如果一个字符串正着读和反着读是一样的,那么它就是回文串。
比如:
12321 a aba aaaa tattattattat
1. Brute-force:
最简单粗暴的解法:找到字符串的所有子串,遍历每一个子串以验证它们是否为回文串。
一个子串由起点和终点决定,因此对于一个长度为n的字符串,一共有个子串,这些子串的平均长度大约是n/2,所以这个解法的时间复杂度为
2. 改进的方法:
显然,对于所有的回文串都是对称的!
长度为奇数的回文串以中间字符为对称轴左右对称,长度为偶数的回文串的对称轴在中间两个字符之间的空隙。能否利用这个性质来提高效率呢?当然!
我们知道整个字符串中的所有字符以及字符间的空隙,都可能是某个回文串的对称轴位置-----我们可以遍历这些位置,在每个位置上同时向左右两边扩展,直到左右两边的字符不相同或者是达到边界为止。对于一个长度为n的字符串,这样的位置一共有n + n - 1 = 2n -1个,在每个位置上大约平均要进行n/4(就是n/2之后再/2)次字符比较,于是此算法的时间复杂度为.
3. Manacher算法(马拉车算法)
对于一个较长的字符串,上面的复杂度是难以接受的,Can we do better?
来看看解法二存在的缺陷:
- 由于回文串长度的奇偶性造成了不同性质的对称轴位置,解法二要对奇偶两种情况分别处理
- 很多子串被重复访问很多次,造成较差的时间复杂度。
缺陷2可以这样看出来:
char: a b a b a
i : 0 1 2 3 4
当i == 1或者 i==