647 回文子串
思路:首先定义一个二维bool类型的dp数组,dp[i][j]表示s中从i到j这个子串是否是回文串。然后从后往前遍历s的每一个字符,同时从该字符开始向后遍历,判断是否是回文串,并将结果累加到结果result中。
如果s[i] == s[j],那么说明以s[i]和s[j]为首尾的子串可能是回文串,需要进一步判断。如果j-i<=1,说明该子串长度为1或2,肯定是回文串;如果dp[i+1][j-1]为true,说明该子串去掉首尾字符后仍为回文串,因此以s[i]和s[j]为首尾的子串是回文串,将dp[i][j]标记为true。
最终返回result即可,表示s中回文子串的数量。
1.动态规划
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[i] == s[j] && (j - i <= 1 || dp[i + 1][j - 1])){
result++;
dp[i][j] = true;
}
}
}
return result;
}
};
516.最长回文子序列
思路:首先定义一个二维int类型的dp数组,dp[i][j]表示s中从i到j这个子串的最长回文子序列长度。初始化dp数组的对角线上的元素,即dp[i][i] = 1,表示单个字符本身就是一个回文子序列。
然后从后往前遍历s的每一个字符,同时从该字符开始向后遍历。当s[i] == s[j]时,说明以s[i]和s[j]为首尾的子串可以构成回文子序列,所以dp[i][j] = dp[i+1][j-1] + 2;当s[i] != s[j]时,说明以s[i]和s[j]为首尾的子串无法构成回文子序列,需要从dp[i+1][j]和dp[i][j-1]中取最大值作为当前dp[i][j]的值。
最终返回dp[0][s.size()-1]即可,表示整个字符串s的最长回文子序列长度。
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 + 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];
}
};