- 最长回文子序列
给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。
子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。
示例 1:
输入:s = “bbbab”
输出:4
解释:一个可能的最长回文子序列为 “bbbb” 。
示例 2:
输入:s = “cbbd”
输出:2
解释:一个可能的最长回文子序列为 “bb” 。
提示:
1 <= s.length <= 1000
s 仅由小写英文字母组成
题目解析:
动态规划dp
设
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j] 表示从 i~j 的最长的回文子序列长度,答案计算
d
p
[
0
]
[
n
−
1
]
dp[0][n-1]
dp[0][n−1]
如果
s
[
i
]
=
=
s
[
j
]
s[i]==s[j]
s[i]==s[j] 说明下标s[i],s[j]一定在回文子序列中,则,
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j] =
d
p
[
i
+
1
]
[
j
−
1
]
+
2
dp[i+1][j-1]+2
dp[i+1][j−1]+2
否则,s[i]和s[j]一定不能同时出现在回文子序列中,那么转移方程为
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
+
1
]
[
j
]
,
d
p
[
i
]
[
j
−
1
]
)
+
1
;
dp[i][j] = min(dp[i+1][j],dp[i][j-1])+1;
dp[i][j]=min(dp[i+1][j],dp[i][j−1])+1;
class Solution {
public:
//dp[i][j] 表示从 i~j的最长的回文子序列长度,计算dp[0][n-1]
//dp[i][j] = dp[i+1][j-1]+2
//dp[i][j] = min(dp[i+1][j],dp[i][j-1])+1;
int longestPalindromeSubseq(string s) {
int dp[1005][1005];
for(int i=0; i<=s.size(); ++i)
dp[i][i] = 1;
int n = s.size();
for(int i=n; i>=0; --i){
for(int j=i+1; j<=n; ++j){
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 dp[0][n-1];
}
};