Skip to content

Latest commit

 

History

History
39 lines (28 loc) · 2.32 KB

File metadata and controls

39 lines (28 loc) · 2.32 KB

Manacher 算法

为了表述方便,我们定义一个新概念臂长,表示中心扩展算法向外扩展的长度。如果一 个位置的最大回文字符串长度为 2 * length + 1 ,其臂长为length

下面的讨论只涉及长度为奇数的回文字符串。长度为偶数的回文字符串我们将会在最后与长 度为奇数的情况统一起来。

思路和算法

在中心扩展算法的过程中,我们能够得出每个位置的臂长。那么当我们要得出以下一个位置 i 的臂长时,能不能利用之前得到的信息呢?

答案是肯定的。具体来说,如果位置 j 的臂长为 length,并且有 j + length > i,如下图所示:

longest-palindromic-substring-manacher

当在位置 i 开始进行中心拓展时,我们可以先找到 i 关于 j 的对称点 2 * j - i。那么如果点 2 * j - i 的臂长等于 n,我们就可以知道,点 i 的臂 长至少为 min(j + length - i, n)。那么我们就可以直接跳过 ii + min(j + length - i, n) 这部分,从 i + min(j + length - i, n) + 1 开始拓 展。

我们只需要在中心扩展法的过程中记录右臂在最右边的回文字符串,将其中心作为 j,在 计算过程中就能最大限度地避免重复计算。

那么现在还有一个问题:如何处理长度为偶数的回文字符串呢?

我们可以通过一个特别的操作将奇偶数的情况统一起来:我们向字符串的头尾以及每两个字 符中间添加一个特殊字符 #,比如字符串 aaba 处理后会变成 #a#a#b#a#。那么原先 长度为偶数的回文字符串 aa 会变成长度为奇数的回文字符串 #a#a#,而长度为奇数的 回文字符串 aba 会变成长度仍然为奇数的回文字符串 #a#b#a#,我们就不需要再考虑 长度为偶数的回文字符串了。

注意这里的特殊字符不需要是没有出现过的字母,我们可以使用任何一个字符来作为这个特 殊字符。这是因为,当我们只考虑长度为奇数的回文字符串时,每次我们比较的两个字符奇 偶性一定是相同的,所以原来字符串中的字符不会与插入的特殊字符互相比较,不会因此产 生问题。