数据结构与算法之 leetcode 字符串回文 中心扩展 / Manacher 算法

数据结构与算法阿木 发布于 5 天前 2 次阅读


字符串回文:中心扩展与Manacher算法

字符串回文是一个经典的计算机科学问题,指的是一个字符串可以从前向后读和从后向前读都相同的特性。在LeetCode等编程竞赛平台上,字符串回文问题经常以不同的形式出现,如判断一个字符串是否是回文、找到字符串的最长回文子串等。解决这类问题,我们可以采用中心扩展法和Manacher算法两种方法。

中心扩展法

中心扩展法是一种简单直观的解决字符串回文问题的方法。其基本思想是:对于字符串中的每一个字符,将其视为回文的中心,然后向左右两边扩展,直到不再满足回文的条件为止。

代码实现

以下是一个使用中心扩展法判断字符串是否为回文的Python代码示例:

python

def is_palindrome(s: str) -> bool:


def expand_around_center(left: int, right: int) -> bool:


while left >= 0 and right < len(s) and s[left] == s[right]:


left -= 1


right += 1


return left + 1 >= right - 1

for i in range(len(s)):


奇数长度的回文


if expand_around_center(i, i):


return True


偶数长度的回文


if expand_around_center(i, i + 1):


return True


return False


分析

中心扩展法的时间复杂度为O(n^2),空间复杂度为O(1)。对于较长的字符串,这种方法可能会比较慢。

Manacher算法

Manacher算法是一种更高效的解决字符串回文问题的算法。它通过预处理字符串,将原字符串转换为一个新的字符串,使得原字符串中的所有字符都位于新字符串的奇数位置,从而简化了回文子串的判断。

代码实现

以下是一个使用Manacher算法找到字符串最长回文子串的Python代码示例:

python

def longest_palindromic_substring(s: str) -> str:


预处理字符串


def preprocess(s: str) -> str:


return '^' + ''.join(s) + '$'

初始化


T = preprocess(s)


n = len(T)


P = [0] n


C = R = 0

Manacher算法


for i in range(1, n - 1):


i_mirror = 2 C - i


P[i] = (R > i) and min(R - i, P[i_mirror])

尝试扩展回文


while T[i + 1 + P[i]] == T[i - 1 - P[i]]:


P[i] += 1

更新中心点和右边界


if i + P[i] > R:


C, R = i, i + P[i]

找到最长回文子串的长度和起始位置


max_len, start = max((n, i) for i, n in enumerate(P))


return s[(start - max_len) // 2: (start + max_len) // 2]


分析

Manacher算法的时间复杂度为O(n),空间复杂度为O(n)。这种方法在处理较长的字符串时,效率远高于中心扩展法。

总结

在解决字符串回文问题时,我们可以根据实际情况选择中心扩展法或Manacher算法。中心扩展法简单直观,但效率较低;而Manacher算法效率较高,但实现较为复杂。在实际应用中,我们需要根据问题的具体要求和数据规模来选择合适的算法。

扩展阅读

1. 《算法导论》 - Robert Sedgewick, Kevin Wayne

2. 《编程之美》 - 陈数,李开复

3. LeetCode官方文档 - https://leetcode-cn.com/

通过学习这些资料,我们可以更深入地理解字符串回文问题的解决方法,并在实际编程中灵活运用。