返回

利用动态规划查找最长回文子串:LeetCode 5 号问题详解

前端







**导言** 

在字符串处理问题中,查找回文子串是一个常见的挑战。回文子串是指正向和反向读起来都相同的子串。在 LeetCode 5 号问题中,我们被要求找出给定字符串中最长的回文子串。

**动态规划方法** 

动态规划是一种自底向上的算法,它将问题分解成较小的子问题,并使用之前子问题的解决方案逐步构建最终答案。在本例中,我们可以定义一个二维布尔数组 `dp[i][j]`,其中 `i` 和 `j` 分别表示字符串 `s` 的起始和结束索引。`dp[i][j]` 为 `true` 表示子串 `s[i:j]` 是回文,否则为 `false`。

**算法步骤** 

1. **初始化:** 设置对角线元素 `dp[i][i]` 为 `true`,因为单个字符总是回文。
2. **两字符子串:** 检查所有长度为 2 的子串 `s[i:i+1]`。如果 `s[i] == s[i+1]`,则 `dp[i][i+1]` 设置为 `true`。
3. **递推:** 对于所有长度大于 2 的子串,使用以下递推公式:

    ```
    dp[i][j] = dp[i+1][j-1] && (s[i] == s[j])
    ```

    如果子串 `s[i+1:j-1]` 是回文,并且字符 `s[i]` 等于 `s[j]`,则子串 `s[i:j]` 也是回文。

**代码示例** 

```python
def longestPalindrome(s: str) -> str:
    n = len(s)
    dp = [[False] * n for _ in range(n)]

    max_len = 1
    start = 0
    
    # 初始化对角线元素
    for i in range(n):
        dp[i][i] = True
    
    # 检查长度为 2 的子串
    for i in range(n-1):
        if s[i] == s[i+1]:
            dp[i][i+1] = True
            if max_len < 2:
                max_len = 2
                start = i
    
    # 递推求解
    for k in range(3, n+1):
        for i in range(n-k+1):
            j = i + k - 1
            if s[i] == s[j] and dp[i+1][j-1]:
                dp[i][j] = True
                if max_len < k:
                    max_len = k
                    start = i
    
    return s[start:start+max_len]

示例用例

  • 输入: "babad"

  • 输出: "bab"

  • 输入: "cbbd"

  • 输出: "bb"

  • 输入: "a"

  • 输出: "a"

总结

利用动态规划算法,我们可以有效地解决 LeetCode 5 号问题,查找字符串中最长的回文子串。该算法具有时间复杂度为 O(n^2) 和空间复杂度为 O(n^2),其中 n 是字符串的长度。通过逐步构建回文子串的解决方案,该算法提供了清晰和高效的方法来解决此类问题。