468 字
2 分钟
代码随想录算法训练营第四十天 | 动态规划 Part13

647. 回文子串#

LeetCode 647. Palindromic Substrings

解题思路

  • 使用二维动态规划数组 dp[i][j] 表示子串 s[i:j+1] 是否为回文。
  • 初始化时,所有单个字符均为回文子串,dp[i][i] = True
  • 状态转移:
    • s[i] == s[j],且
      • 子串长度为 1 或 2 (j - i <= 1),则为回文。
      • 否则取决于 dp[i+1][j-1] 是否为回文。
  • 遍历顺序:i 从后往前遍历,ji 往后遍历。
class Solution:
def countSubstrings(self, s: str) -> int:
n = len(s)
dp = [[False] * n for _ in range(n)]
res = 0
# 单个字符是回文子串
for i in range(n):
dp[i][i] = True
res += 1
# 从后向前遍历 i,保证转移时 dp[i+1][j-1] 已计算
for i in range(n - 1, -1, -1):
for j in range(i + 1, n):
if s[i] == s[j]:
if j - i == 1 or dp[i + 1][j - 1]:
dp[i][j] = True
res += 1
return res

516. 最长回文子序列#

LeetCode 516. Longest Palindromic Subsequence

解题思路

  • 使用二维动态规划数组 dp[i][j] 表示子串 s[j:i+1] 的最长回文子序列长度。

  • 初始化时,所有单个字符长度为 1。

  • 状态转移:

    • s[i] == s[j],则 dp[i][j] = dp[i - 1][j + 1] + 2, 即包含 s[i]s[j] 两个字符加上中间子串的最长回文子序列长度。
    • 否则,取舍去 s[i]s[j] 后的最大值: dp[i][j] = max(dp[i - 1][j], dp[i][j + 1])
  • 遍历顺序:

    • i 从前向后,ji-1 向前遍历,保证访问状态正确。
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
n = len(s)
dp = [[0] * n for _ in range(n)]
# 单字符最长回文长度为 1
for i in range(n):
dp[i][i] = 1
# i 右边界从小到大遍历
for i in range(1, n):
# j 左边界从 i-1 向前遍历,保证 j < i
for j in range(i - 1, -1, -1):
if s[i] == s[j]:
dp[i][j] = dp[i - 1][j + 1] + 2
else:
dp[i][j] = max(dp[i - 1][j], dp[i][j + 1])
# 最大值一定在最后一行
return max(dp[n - 1])
代码随想录算法训练营第四十天 | 动态规划 Part13
https://fuwari.vercel.app/posts/code_musings_day_forty/
作者
Jarrett
发布于
2025-07-26
许可协议
CC BY-NC-SA 4.0