[516][中等][动态规划] 最长回文子序列
题目描述
给定一个字符串 s ,找到其中最长的回文子序列,并返回该序列的长度。可以假设 s 的最大长度为 1000 。
示例 1:
输入:
"bbbab"
输出:
4
一个可能的最长回文子序列为 "bbbb"。
示例 2:
输入:
"cbbd"
输出:
2
一个可能的最长回文子序列为 "bb"。
提示:
1 <= s.length <= 1000
s 只包含小写英文字母
解题思路
使用动态规划的方法.
状态
f[i][j] 表示 s 的第 i 个字符到第 j 个字符组成的子串中,最长的回文序列长度是多少。
转移方程
如果 s 的第 i 个字符和第 j 个字符相同的话
f[i][j] = f[i + 1][j - 1] + 2
如果 s 的第 i 个字符和第 j 个字符不同的话
f[i][j] = max(f[i + 1][j], f[i][j - 1])
初始化
f[i][i] = 1 单个字符的最长回文序列是 1
结果
f[0][n - 1]
遍历顺序
由于计算f[i][j]时可能需要 f[i+1][j-1] 即左下, f[i+1][j] 即下方, f[i][j - 1]即左方,
对角线的值在初始化时都确定时1, 因此在遍历时, i从最后向前遍历, j从i + 1遍历到n - 1, 这样可以保证每个子问题都已经算好了.
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
n = len(s)
if not n:
return 0
f = [[1] * n for _ in range(n)]
for i in range(n - 1, -1, -1):
for j in range(i + 1, n):
if s[i] == s[j]:
f[i][j] = f[i + 1][j - 1] + 2 if j - i > 1 else 2
else:
f[i][j] = max(f[i + 1][j], f[i][j - 1])
return f[0][n - 1]
参考资料
最后更新于
这有帮助吗?