516. 最长回文子序列
给定一个字符串 s ,找到其中最长的回文子序列,并返回该序列的长度。可以假设 s 的最大长度为 1000 。
示例 1:
输入:“bbbab”
输出: 4
解释: 一个可能的最长回文子序列为 “bbbb”。
示例 2:
输入: “cbbd”
输出: 2
解释: 一个可能的最长回文子序列为 “bb”。
动态规划——DP
刚开始做提的时候我没有理解子序列的意思,理解为子串,导致做题思路错误,这里说一下定义
- 一个字符串 s 被称作另一个字符串 S 的子串,表示 s 在 S 中出现了
- 一个字符串 s 被称作另一个字符串 S 的子序列,说明从序列 S 通过去除某些元素但不破坏余下元素的相对位置(在前或在后)可得到序列 s
所以我们的状态转移方程应为
d
p
[
i
]
[
j
]
=
{
d
p
[
i
+
1
]
[
j
−
1
]
+
2
s
[
i
]
=
=
s
[
j
]
m
a
x
(
d
p
[
i
+
1
]
[
j
]
,
d
p
[
i
]
[
j
−
1
]
)
e
l
s
e
dp[i][j]=\left\{ \begin{array}{rcl} dp[i + 1][j - 1] + 2 & & s[i] == s[j]\\ max(dp[i + 1][j], dp[i][j - 1]) & & else\\ \end{array} \right.
dp[i][j]={dp[i+1][j−1]+2max(dp[i+1][j],dp[i][j−1])s[i]==s[j]else
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
n = len(s)
dp = [[0]*n for _ in range(n)]
#反着遍历保证状态的正确转移
for i in range(n-1,-1,-1):
dp[i][i] = 1
for j in range(i+1, n):
if s[i] == s[j]:
dp[i][j] = dp[i+1][j-1] + 2
else:
dp[i][j] = max(dp[i][j-1], dp[i+1][j])
return dp[0][n-1]