📜  最短回文子串(1)

📅  最后修改于: 2023-12-03 15:26:28.082000             🧑  作者: Mango

最短回文子串

当我们要找到一个最短的回文子串时,可以使用 Manacher's Algorithm,这个算法可以实现线性时间的复杂度。

算法介绍

Manacher's Algorithm 通过利用回文对称性,利用已经处理过的回文串信息,来发现新的回文串。在这个算法中,我们利用了回文对称性的一个性质:对于一个回文串 $s$, 它的反序列 $s^R$ 恰好与 $s$ 一致的。

算法流程

接下来介绍 Manacher's Algorithm 的流程。

  1. 初始化中心点 $C$ 和右边界 $R$,其中 $C$ 表示当前找到的回文中心,$R$ 表示这个回文的右边界。
  2. 如果当前点 $i$ 满足 $i < R$,则通过已经处理过的 $C$ 和 $R$ ,找到 $i$ 对应的 $j$ 点从而利用回文对称性,并判断是否可以从 $s_j$ 继续向外拓展寻找回文,如果是,则继续向外拓展;否则退出循环。在拓展的过程中,更新新的中心点 $C$ 和 右边界 $R$。这个过程中记录已知的最长回文串的信息。
  3. 如果当前点 $i$ 满足 $i \ge R$,则直接从该点开始拓展寻找回文。在拓展的过程中更新中心点 $C$ 和 右边界 $R$,记录已知的最长回文串的信息。

在完成上面的操作之后,我们可以得到最长回文子串的长度和其中心位置。

示例代码

下面是 Manacher's Algorithm 的示例代码,其中的变量 i,j,r 和 p 分别表示当前点的下标,对称中心的下标,以及最长回文串右边界和中心位置。变量 MaxLen 存储最长回文串的长度。

def manacher(s):
    n = len(s)
    if n < 2:
        return s
    t = '#'.join('^{}$'.format(s))
    MaxLen = 0
    Center = 0
    Radius = 0
    P = [0] * len(t)
    for i in range(1, len(t) - 1):
        if Radius > i:
            P[i] = min(Radius - i, P[2 * Center - i])
        else:
            P[i] = 0
        while t[i + 1 + P[i]] == t[i - 1 - P[i]]:
            P[i] += 1
        if i + P[i] > Radius:
            Center, Radius = i, i + P[i]
        if P[i] > MaxLen:
            MaxLen = P[i]
            p = (i - MaxLen) // 2
    return s[p:p + MaxLen]
总结

Manacher's Algorithm 是一种很有效也很经典的算法,它可以帮助我们高效地寻找最短回文子串。在处理字符串的题目时,我们可以优先考虑使用此算法来解决问题。