Given a string s, find the longest palindromic subsequence’s length in s. You may assume that the maximum length of s is 1000.
Example 1:
Input:
"bbbab"
Output:
4
One possible longest palindromic subsequence is “bbbb”.
Example 2:
Input:
"cbbd"
Output:
2
One possible longest palindromic subsequence is “bb”.
题意
思路1
- 定义一个二维的
dp[i][j]
来表示字符串第i
个字符到第j
个字符的长度,子问题也就是每个子回文字符串的长度。 - 对于
d[i][j]
,我们根据上题的分析依然可以看出, 当s[i]
和s[j]
相等时,s[i+1...j-1]
这个字符串加上2就是最长回文子序列; 当s[i]
和s[j]
不相等时,就说明可能只有其中一个出现在s[i,j]的最长回文子序列中,我们只需要取s[i-1,j-1]
加上s[i]
或者s[j]
的数值中较大的; 综上所述,状态转移方程也就可以写成:
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])
- 从下往上,从左往右更新
dp
所有的值 - 始化条件 很明显看出来的当只有一个字符的时候,最长回文子序列就是1,所以可以得到
dp[i][j]=1(i=j)
接下来我们来看看 当i>j
时,不符合题目要求,不存在子序列,所以直接初始化为0。 当`i时,每次计算表中对应的值就会根据前一个状态的值来计算。 dp[0][len - 1]
即表示起点为0
终点为n-1
的字符串的最大回文长度
代码1
class Solution {
public:
int longestPalindromeSubseq(string s) {
int len = s.size();
vector<vector<int>> dp(len, vector<int>(len));
for(int i = 0; i < len; i++)
dp[i][i] = 1;
for(int i = len - 1; i >= 0; i--)
{
for(int j = i + 1; j < len; j++)
{
if(s[i] == s[j]) // 两个字符相等时,子字符串+2
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][len - 1];
}
};