题目:647. 回文子串
文章链接:代码随想录
视频链接:LeetCode:647.回文子串
题目链接:力扣题目链接
图释:
class Solution {
public:
int countSubstrings(string s) {
// dp[i][j]数组表述,区间范围[i,j](左闭右闭)的子串是否是回文子串,是为true, 不是为false
// 分两种情况:s[i]==s[j] s[i]!=s[j]
// 递推公式: s[i]!=s[j]时,很明显不是回文子串
// s[i]==s[j]时,下标i与下标j相同着,'a' 是回文子串
// 下标i与下标j相差1,'bab' 是回文子串
// 下标i与下标j相差大于1,'davd'则要考虑中间是都为回文子串,如果dp[i+1][j-1]是回文子串则也为回文子串
// 遍历顺序:dp[i][j]由dp[i+1][j-1],↙左下角推导出来的,故要先遍历,即从左往右,从下往上遍历
// 初始化:初始化为false
vector<vector<bool>>dp(s.size(), vector<bool>(s.size(), false));
int result = 0; // 回文子串的数目
// eg 'aaa'
for(int i=s.size()-1; i>=0; i--){ //i从2开始
for(int j=i; j<s.size(); j++){ // j=i=2 也即从dp[2][2]开始
if(s[i]==s[j]){ // s[i]==s[j] 为回文子串
if(j-i<=1) { //情况1、2
result++;
dp[i][j]=true;
}
else if(dp[i+1][j-1]){ //直接判断了,中间为回文子串
result++;
dp[i][j]=true;
}
}
}
}
return result;
}
};
题目:516.最长回文子序列
文章链接:代码随想录
视频链接:LeetCode:516.最长回文子序列
题目链接:力扣题目链接
图释:
class Solution {
public:
int longestPalindromeSubseq(string s) {
// dp[i][j]数组的含义:s[i]-s[j]范围内的最长回文子序列(不要求连续)
// 分两种情况:当s[i]==s[j]时,子序列增加两个 dp[i][j] =dp[i+1][j-1]+2
// 当s[i]!=s[j]时,分情况进行讨论, dp[i][j] = max(dp[i+1][j], dp[i][j-1]+1) 两遍各增加一个,取最大值
// 初始化: 第一列和最后一行除了dp[0][0]和dp[s.size()-1][s.size()-1]
vector<vector<int>> dp(s.size(), vector<int>(s.size(), 0));
for(int i=0; i<s.size(); i++) dp[i][i]=1; //当i=j时,必为回文序列并且长度为1
for(int i=s.size()-1; i>=0; i--){
for(int j=i+1; j<s.size(); j++){ // j比i大
if(s[i]==s[j]) dp[i][j]= dp[i+1][j-1]+2;
else{
dp[i][j] = max(dp[i][j-1], dp[i+1][j]);
}
}
}
return dp[0][s.size()-1];
}
};