647. 回文子串
思路:两数相等相等时 分三种情况,如果头尾长度相差等于0,则dp[i][j]=1;相差等于1说明两个元素紧贴,直接就是回文串dp[i][j]=1;如果大于1,则需要内部子串dp[i+1][j-1]也是回文串,才能是回文串,否则不是。默认初始化为false
动规五部曲:
1.dp[i][j]下标及其含义 以s[i-1]为开头s[j-1]为结尾的子串的是否为回文子串
2.递推公式:三种情况 i=j i-j=1 i-j>1
//相同:if(s[i]==s[j])
//if(i==j)dp[i][j]=true; res++;
//else if(j-i==1) dp[i][j]=true; res++;
//else{if(dp[i+1][j-1]==true) res++};如果子串内部回文 则子串回文
//不相同都是false 不需要操作
3.初始化:false
4.遍历顺序:由于dp[i][j]有时候需要dp[i+1][j-1]决定 所以需要从下到上 从左到右遍历
代码:
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){
dp[i][j]=true;
res++;
}
else{
if(dp[i+1][j-1]==true){
dp[i][j]=true;
res++;
}
}
}
}
}
return res;
}
};
516.最长回文子序列
思路:相比于上一道题回文子串,回文子序列可以删除中间元素,所以我们只需要求从i到j回文子串的最大长度就可以了,然后随着ij的变化继续累加即可。如果碰到不相等的元素,则尝试删掉两边的一个元素,看是否是回文串,然后求其长度。
动规五部曲:
1.dp[i][j] i开头j结尾的最长回文子序列长度
2.递推公式:相等 dp[i][j]=j-i+1; 不相等 dp[i][j]=max(dp[i-1][j],dp[i][j-1])
3.初始化:1
4.遍历顺序:从上到下 从左到右
代码:
class Solution {
public:
int longestPalindromeSubseq(string s) {
vector<vector<int>> dp(s.size(), vector<int>(s.size(), 0));
dp[0][0] = 1;
for(int i=0;i<s.size();i++){
dp[i][i]=1;
}
//回文子串的长度
int res = 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];
}
};