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]
是否为回文。
- 子串长度为 1 或 2 (
- 若
- 遍历顺序:
i
从后往前遍历,j
从i
往后遍历。
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
从前向后,j
从i-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/