📜  最长回文子串的长度(1)

📅  最后修改于: 2023-12-03 14:55:22.920000             🧑  作者: Mango

最长回文子串的长度

介绍

回文串是指正读和反读都相同的字符串。最长回文子串是指在一个字符串中,最长的回文子串的长度。解决这个问题的算法有多种,无论是暴力算法还是优化的算法都有其独特之处。

算法
暴力算法

暴力算法是最容易想到的算法。它的思路是枚举所有可能的子串,并在其中寻找最长的回文子串。

def longestPalindrome(s: str) -> int:
    n = len(s)
    ans = 0
    for i in range(n):
        for j in range(i, n):
            if s[i:j+1] == s[i:j+1][::-1]:
                ans = max(ans, j-i+1)
    return ans

时间复杂度为 $O(n^3)$,空间复杂度为 $O(1)$,其运行速度较慢。

中心扩展算法

中心扩展算法是优化暴力算法的一种方法。它的思路是枚举所有可能成为回文串中心的位置,并从这些中心开始向两边扩散,直到无法扩展为止。

def longestPalindrome(s: str) -> int:
    n = len(s)
    ans = 0
    for i in range(n):
        # 以i为回文中心,向两边扩展
        l, r = i, i
        while l >= 0 and r < n and s[l] == s[r]:
            l -= 1
            r += 1
        ans = max(ans, r-l-1)

        # 以i和i+1为回文中心,向两边扩展
        l, r = i, i+1
        while l >= 0 and r < n and s[l] == s[r]:
            l -= 1
            r += 1
        ans = max(ans, r-l-1)
    return ans

时间复杂度为 $O(n^2)$,因为每个中心最多扩展 $n$ 次。空间复杂度为 $O(1)$。

Manacher 算法

Manacher 算法是一种更加高效的算法。它的思路是在中心扩展算法的基础上进行优化。它基于回文串的对称性,在枚举每个中心时,可以利用之前已经求解过的回文串信息,避免重复计算。

def longestPalindrome(s: str) -> int:
    n = len(s)
    t = '#'.join('^{}$'.format(s))
    p = [0] * len(t)
    center, right = 0, 0
    for i in range(1, len(t)-1):
        if i < right:
            p[i] = min(right-i, p[2*center-i])
        while t[i+p[i]+1] == t[i-p[i]-1]:
            p[i] += 1
        if i+p[i] > right:
            center, right = i, i+p[i]
    return max(p)+1

时间复杂度为 $O(n)$,空间复杂度为 $O(n)$。

总结

在解决最长回文子串问题时,暴力算法是最容易想到的。但是其时间复杂度较高,不适用于大规模数据。中心扩展算法是经典的优化算法,时间复杂度为 $O(n^2)$。Manacher 算法是最优解,时间复杂度为 $O(n)$,空间复杂度也为 $O(n)$。因此在实际应用中,建议使用 Manacher 算法。