647. 回文子串
知识点:动规
状态:看思路自己写
思路:
dp不好想,dp[i][j] 是指左闭右闭时,是否为回文,bool类型;
注意递归公式和遍历顺序
class Solution {
public:
int countSubstrings(string s) {
int res=0;
vector<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;
}
};
516. 最长回文子序列
知识点:动规
状态:不会
思路:
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<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];
}
};
卡哥总结:
代码随想录 (programmercarl.com)