最长回文子序列(LeetCode-516)
题目
给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。
子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。
示例 1:
输入:s = "bbbab" 输出:4 解释:一个可能的最长回文子序列为 "bbbb" 。
示例 2:
输入:s = "cbbd" 输出:2 解释:一个可能的最长回文子序列为 "bb" 。
提示:
1 <= s.length <= 1000
s 仅由小写英文字母组成
思路
五部曲
dp[i][j] 含义
在区间范围为 [ i , j ] (注意左右都是闭区间)内的最长的回文子序列的长度
递推公式
当 s [ i ] ≠ s [ j ]时,只说明二者不能同时加入回文子串,可以分别加入求最大值,d p [ i ] [ j ] = m a x ( d p [ i + 1 ] [ j ] , d p [ i ] [ j − 1 ] )
当 s [ i ] = s [ j ] 时,d p [ i ] [ j ] = d p [ i + 1 ] [ j − 1 ] + 2
数组初始化
当下标 i = j 时,即一个字符的回文子序列长度应该为一
遍历顺序
要注意看当前元素依靠谁的状态获取,看到递推公式,就知道肯定对于 i 的遍历肯定要倒序。
代码展示
class Solution { public: int longestPalindromeSubseq(string s) { int n = s.size(); if (n == 1) { return 1; } vector<vector<int>> dp(n, vector<int>(n)); for (int i = n - 2; i >= 0; i--) { dp[i][i] = 1; 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]; } };