LeetCode 647. 回文子串
题目链接:647. 回文子串
踩坑:分情况和遍历顺序很重要
思路:
- dp数组的含义:dp[i][j]:以i开始,j结尾的s是否是回文串
- 递推公式:如果s[i] == s[j],则如果 i 等于 j 或相邻则true,如果 i 与 j 不相邻则判断dp[i+1][j-1]。
- 初始化:因为递推公式考虑到了单个元素的情况,所以不需要单独初始化,因此全部为false即可
- 遍历顺序:由递推公式可知,本题需要从下向上,从左到右遍历
代码:
class Solution {
public:
int countSubstrings(string s) {
vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));
int result = 0;
for(int i = s.size()-1; i >= 0; i--)
{
for(int j = i; j < s.size(); j++)
{
if(s[j] == s[i])
{
if(j - i > 1)
{
if(dp[i+1][j-1] == true)
{
dp[i][j] = true;
result++;
}
}
else
{
dp[i][j] = true;
result++;
}
}
}
}
return result;
}
};
LeetCode 516.最长回文子序列
题目链接:516.最长回文子序列
踩坑:这种回文串类的题目一定要分成 i = j,j-i = 1,j-i > 1
思路:本题与上题的区别在于本题的要求不是连续的
- dp数组的含义:dp[i][j]:以i开始,j结尾的s的最长回文子序列长度
- 递推公式:若s[i] == s[j],dp[i][j] = dp[i+1][j-1] + 2(实际要细分情况),否则,dp[i][j] = max(dp[i+1][j],dp[i][j-1])
- 初始化:如果在递推公式中考虑了细分情况就不需要初始化了,如果没考虑则要初始化dp[x][x] = 1
- 遍历顺序:由递推公式可知,需要从下向上,从左到右
代码:
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; j < s.size(); j++)
{
if(s[i] == s[j])
{
if(j - i > 1) dp[i][j] = dp[i+1][j-1] + 2;
else if(j - i == 1) dp[i][j] = 2;
}
else dp[i][j] = max(dp[i+1][j], dp[i][j-1]);
}
}
return dp[0][s.size()-1];
}
};