dp不好想,dp[i][j] 是指左闭右闭时,是否为回文,bool类型;
注意递归公式和遍历顺序
- class Solution {
- public:
- int countSubstrings(string s) {
- int res=0;
- vector
bool>> dp(s.size(),vector<bool>(s.size(), false)); - //dp[i][j] 是指左闭右闭时,是否为回文,bool
- // s[i] != s[j] 时,肯定不是回文
- //相等时,三种情况,1. i和j也相等,回文 2. i和j差一,回文 3. 差的大于1,看dp[i+1][j-1]时候是回文
- for(int i = s.size() - 1 ; 0<=i; i-- ) {
- for(int j = i; j < s.size(); j++){
- if( s[i] == s[j]) {
- if( j - i <= 1) {
- res++;
- dp[i][j] = true;
- }
- else if( dp[i+1][j-1] ){
- res++;
- dp[i][j] = true;
- }
- }
- }
- }
- return res;
- }
- };
dp[i][j]:字符串s在[i, j]范围内最长的回文子序列的长度为dp[i][j]。
在判断回文子串的题目中,关键逻辑就是看s[i]与s[j]是否相同。
如果s[i]与s[j]相同,那么dp[i][j] = dp[i + 1][j - 1] + 2;
如果s[i]与s[j]不相同,说明s[i]和s[j]的同时加入 并不能增加[i,j]区间回文子串的长度,那么分别加入s[i]、s[j]看看哪一个可以组成最长的回文子序列。
加入s[j]的回文子序列长度为dp[i + 1][j]。
加入s[i]的回文子序列长度为dp[i][j - 1]。
那么dp[i][j]一定是取最大的,即:dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
初始化:当i与j相同,那么dp[i][j]一定是等于1的,即:一个字符的回文子序列长度就是1。
- class Solution {
- public:
- int longestPalindromeSubseq(string s) {
- vector
int>> dp(s.size(), vector<int>(s.size(), 0)); - for (int i = 0; i < s.size(); i++) dp[i][i] = 1;
- for (int i = s.size() - 1; i >= 0; i--) {
- for (int j = i + 1; j < s.size(); 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][s.size() - 1];
- }
- };
-
卡哥总结: