第一题:
思路:
dp[i][j]的含义:表示从i到j之间的子串是否是回文子串。
那么考虑三种情况:
在s[i] == s[j]的前提下:
如果i == j说明当前是一个元素,那么直接res++,表示其中有一个回文子串,
如果j - i == 1说明当前从i到j之间两个元素也是回文子串,那么res也++;
如果j - i > 1的情况,那么可以有递推公式推出,如果dp[i + 1][j - 1]的值为true的话说明i + 1到j - 1这个区间的元素是回文子串,那么再加上两边的两个元素同样还是回文子串,res++;
代码如下:
class Solution {
public:
int countSubstrings(string s) {
int res = 0;
vector<vector<int>> dp(s.size(), vector<int>(s.size(), false));
for(int i = s.size(); i >= 0; i--){
for(int j = i; j < s.size(); j++){
if(s[i] == s[j]){
if(j - i <= 1){
dp[i][j] = true;
res++;
}else if(dp[i + 1][j - 1] == true){
dp[i][j] = true;
res++;
}
}
}
}
return res;
}
};
第二题:
原题链接:516. 最长回文子序列 - 力扣(LeetCode)
思路:
dp[i][j]的含义:表示从i到j之间的最长回文子序列;
注意这里是子串,可以不连续;
如果s[i] == s[j],因为是子序列,所以可以直接在之前最长回文子序列的基础上加2;
如果s[i] != s[j],那么就要分别考虑从 i 到 j - 1 和从 i + 1到 j之间回文子序列的最大值;
注意初始化的时候,如果 i == j的时候将 dp[i][j] 初始化为1;因为这个状态是递推是起始状态,
遍历顺序上也有坑,j 直接从 i + 1开始遍历即可,因为 i == j的情况已经考虑过了。
代码如下:
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];
}
};