本题如果我们定义,dp[i] 为 下标i结尾的字符串有 dp[i]个回文串的话,我们会发现很难找到递归关系。
我们在判断字符串S是否是回文,那么如果我们知道 s[1],s[2],s[3]这个子串是回文的,那么只需要比较 s[0]和s[4]这两个元素是否相同,如果相同的话,这个字符串s 就是回文串。
因此,dp[i][j]:表示区间范围[i,j](注意是左闭右闭)的子串是否是回文子串,如果是dp[i][j]为true,否则为false。
AC代码:
class Solution {
public:
int countSubstrings(string s) {
int n = s.length();
// dp[i][j]:[i,j]范围内的子串是否是回文
vector<vector<bool>> dp(n, vector<bool>(n));
int res = 0;
for (int i = n - 1; i >= 0; --i) {
for (int j = i; j < n; ++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;
}
};
和647. 回文子串类似,对于回文的问题,dp的定义一般都是看一个范围内是否是回文,然后向左右两边扩散递归。
本题也是类似,dp数组:[i,j]范围内的子序列的最长回文子序列
class Solution {
public:
int longestPalindromeSubseq(string s) {
int n = s.size();
vector<vector<int>> dp(n, vector<int>(n, 0));
for (int i = n - 1; i >= 0; i--) {
for (int j = i; j < n; ++j) {
if (s[i] == s[j]) {
if (i == j) {
dp[i][j] = 1;
} else if (j - i == 1) {
dp[i][j] = 2;
} else {
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];
}
};