【647. 回文子串】
这个题目跟以往不一样的地方在于dp数组及下标的含义和遍历的顺序。
因为题目是求回文子串的个数,那么dp数组的含义是回文子串的个数无法往后推导。需要根据回文这个特性来定义dp数组。
dp[i][j]的含义是区间【i,j】子串是否为回文子串。
递推公式分为两种情况。第一种就是s[i]!=s[j],那么以【i,j】为区间的子串肯定不是回文。
第二种情况是s[i]==s[j],那么又可以分为三种情况。
首先是i==j,肯定是回文,因为只有一个字符
其次是i + 1 = j,肯定是回文,因为中间只有一个字符
最后是j - i >1,这样就需要看i+1到j-1这个区间是否为回文,如果是,难么i到j这个区间就是回文,如果不是那么就不是回文。
由此我们可以看到获得dp[i][j]需要从dp[i+1][j-1]得到,所以需要从下往上从左往右遍历,这样才ok。
最后我们来看看最终的代码:
class Solution {
public:
int countSubstrings(string s) {
vector<vector<bool>>dp(s.size(), vector<bool>(s.size(), false));
int res = 0;
for(int i = s.size() - 1; i >= 0; 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;
}
};
注意:j是从i开始的,因为根据dp数组的定义,j一定比i大。
【516.最长回文子序列】
这个题目最重点的是需要知道递推公式的逻辑。
dp数组的含义是从下标i到下标j最长回文子序列的长度。
我们还是需要去比较s [i]和s[j]是否相等。
如果相等的话,那么dp[i][j] = dp[i+1][j-1] + 2
如果不相等的话,那么就需要比较加入s[i]或者加入s[j]哪一个子串拥有最大的回文序列长度。
dp数组的初始化需要初始化下标i = j的情况,都初始化为1就OK。