返回

打造回文之美:探索字符串中的回文子串

前端

算法一览

回文子串的查找算法主要分为两类:暴力法和动态规划法。暴力法虽然简单粗暴,但计算量巨大,时间复杂度为O(n^3)。而动态规划法则可以有效降低时间复杂度,使其达到O(n^2)。此外,Manacher算法和中心扩展算法也是两种高效的算法,可以在线性时间内找到最长回文子串。

暴力法:穷举搜索

暴力法是最直接的回文子串查找算法。它的核心思想是,对于字符串中的每一个子串,都判断它是否为回文子串。如果它是回文子串,就将它保存下来。在所有保存下来的回文子串中,选择最长的一个作为结果。

暴力法的伪代码如下:

function longestPalindrome(string):
    max_length = 0
    max_palindrome = ""
    for i in range(len(string)):
        for j in range(i + 1, len(string) + 1):
            substring = string[i:j]
            if substring == substring[::-1] and len(substring) > max_length:
                max_length = len(substring)
                max_palindrome = substring
    return max_palindrome

动态规划法:递推求解

动态规划法是一种自底向上的算法,它将问题分解成一系列子问题,然后逐个求解子问题,最终得到问题的整体解。

对于回文子串的查找,我们可以定义一个二维布尔数组dp,其中dp[i][j]表示字符串中从第i个字符到第j个字符的子串是否为回文子串。

我们可以使用以下公式来计算dp[i][j]:

dp[i][j] = true if (i == j) or (i + 1 == j and string[i] == string[j]) or (dp[i + 1][j - 1] and string[i] == string[j])

动态规划法的伪代码如下:

function longestPalindrome(string):
    n = len(string)
    dp = [[False] * n for _ in range(n)]
    max_length = 0
    max_palindrome = ""
    for i in range(n - 1, -1, -1):
        dp[i][i] = True
        for j in range(i + 1, n):
            dp[i][j] = (i + 1 == j and string[i] == string[j]) or (dp[i + 1][j - 1] and string[i] == string[j])
            if dp[i][j] and j - i + 1 > max_length:
                max_length = j - i + 1
                max_palindrome = string[i:j + 1]
    return max_palindrome

Manacher算法:线性时间解决

Manacher算法是一种巧妙的算法,它可以在线性时间内找到最长回文子串。

Manacher算法的核心思想是,在字符串中加入特殊字符作为分隔符,然后将字符串变成一个回文串。这样,就可以将回文子串的查找问题转化为最长公共子串的查找问题。

Manacher算法的伪代码如下:

function longestPalindrome(string):
    new_string = "#" + "#".join(string) + "#"
    n = len(new_string)
    p = [0] * n
    center = 0
    right = 0
    max_length = 0
    max_palindrome = ""
    for i in range(1, n - 1):
        p[i] = min(right - i, p[2 * center - i]) if i < right else 0
        while i + p[i] < n and i - p[i] >= 0 and new_string[i + p[i]] == new_string[i - p[i]]:
            p[i] += 1
        if i + p[i] > right:
            center = i
            right = i + p[i]
        if p[i] > max_length:
            max_length = p[i]
            max_palindrome = new_string[i - max_length + 1:i + max_length]
    return max_palindrome

中心扩展算法:简单高效

中心扩展算法也是一种线性时间解决回文子串查找问题的算法。

中心扩展算法的核心思想是,对于字符串中的每一个字符,都以它为中心向两边扩展,直到遇到不同的字符为止。在扩展过程中,记录下最长的回文子串。

中心扩展算法的伪代码如下:

function longestPalindrome(string):
    n = len(string)
    max_length = 0
    max_palindrome = ""
    for i in range(n):
        odd_length = expandAroundCenter(string, i, i)
        even_length = expandAroundCenter(string, i, i + 1)
        current_length = max(odd_length, even_length)
        if current_length > max_length:
            max_length = current_length
            max_palindrome = string[i - (max_length - 1) // 2:i + max_length // 2 + 1]
    return max_palindrome

function expandAroundCenter(string, left, right):
    while left >= 0 and right < len(string) and string[left] == string[right]:
        left -= 1
        right += 1
    return right - left - 1

结语

回文子串的查找是一个经典的算法问题,它在字符串处理、文本挖掘等领域有着广泛的应用。本文介绍了四种常用的回文子串查找算法,包括暴力法、动态规划法、Manacher算法和中心扩展算法。这些算法各有优劣,开发者可以根据具体场景选择合适的算法。