📜  门|门 IT 2006 |问题 10(1)

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

题目介绍

本题为门|门IT 2006年的第10道问题,题目为求字符串中最长回文子串的长度,要求在O(n)的时间复杂度内解决。

解题思路

可借鉴Manacher算法,一种时间复杂度为O(n)的算法,用于找出一个字符串的最长回文子串。Manacher算法实际上是对中心扩展算法的一种优化。

步骤如下:

  1. 在每个字符的左右都插入一个特定字符,比如'#',以便解决奇数长度与偶数长度的问题。
  2. 定义一个数组p,p[i]表示以i为中心的最长回文子串的半径(即回文半径)
  3. 定义变量maxRight,表示已经搜到所有p[i]+i的最大值,并且对应的回文串的右端点为pos
  4. 对于每个i,由于对称性,可以利用已经处理过的回文半径进行快速推导。具体来说,如果i在[maxRight,pos]之间,则p[i]=min(p[2*pos-i],p[pos]+pos-i),否则暴力向两侧扩展。
  5. 更新maxRight和pos
  6. 最后遍历p数组,得到最大回文半径

代码实现

def manacher(s):
    # 在每个字符的左右都插入一个特定字符'#'
    s = '#' + '#'.join(s) + '#'
    n = len(s)
    p = [0] * n
    maxRight = pos = resCenter = resLen = 0
    for i in range(n):
        # 先快速计算出p[i]
        if i < maxRight:
            p[i] = min(p[2 * pos - i], maxRight - i)
        else:
            p[i] = 1
        # 向两侧扩展
        while i - p[i] >= 0 and i + p[i] < n and s[i - p[i]] == s[i + p[i]]:
            p[i] += 1
        # 更新maxRight和pos
        if i + p[i] > maxRight:
            maxRight = i + p[i]
            pos = i
        # 更新最长回文子串的中心和长度
        if p[i] > resLen:
            resLen = p[i]
            resCenter = i
    return resLen - 1 # 最长回文子串的长度为半径-1