题目要求:
给你一个字符串 s
,找出其中最长的回文子序列,并返回该序列的长度。
子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。
示例 1:
输入:s = "bbbab" 输出:4 解释:一个可能的最长回文子序列为 "bbbb" 。
示例 2:
输入:s = "cbbd" 输出:2 解释:一个可能的最长回文子序列为 "bb" 。
提示:
1 <= s.length <= 1000
s
仅由小写英文字母组成
解法-1 动态规划 O(N^2):
这个题要得到字符串s的最长回文子序列,那么我们就可用创建一个二维dp表,dp[i][j]存放区间[j,i]内的最长回文子序列的长度。
如果i == j && s[i]==s[j],只有一个字符,长度为1;
如果i == j+1 && s[i]==s[j],两个相同字符,长度为2;
如果i > j+1 && s[i]==s[j],中间相隔了字符,因为一个回文串两端加上相同的字符,那它还是一个回文串,所以长度为中间的最长回文串+2,即dp[i-1][j+1]+2;
如果 s[i]!=s[j],找中间区间的最长回文串长度即可。
图示如下:
填表顺序,因为要用到 i-1 和 j+1 ,所以填表顺序是由上而下,由右到左 。
class Solution {
public:
int longestPalindromeSubseq(string s) {
int n = s.size();
vector<vector<int>> dp(n);
for(int i = 0;i < n;i++)
dp[i].resize(i+1);
for(int i = 0;i < n;i++)
{
for(int j = i;j >= 0;j--)
{
if(s[i] == s[j])
{
if(i == j)
dp[i][j] = 1;
else if(j == i-1)
dp[i][j] = 2;
else
dp[i][j] = dp[i-1][j+1]+2;
}
else
dp[i][j] = max(dp[i-1][j],dp[i][j+1]);
}
}
return dp[n-1][0];
}
};