647. 回文子串
心得
没思路
题解
-
动态规划法
-
定义dp[i][j] :闭区间[i, j]的子串是否为回文串
-
递推:
- 考虑三种情况,i j等的单字符情况 i j相差1的连续情况(由此也可引入双指针法,对称取决内部1个或者2个元素为中心)
- 情况三,在当前左右对称情况下,判断里面即可即取决于dp[i+1][j-1]
-
遍历顺序:参考遍历顺序,需要先下后上,先左后右
-
初始化:默认都false
-
-
双指针法:
- 考虑由中心元素,两边拓展而成,中心元素可单可双
// 动规 O(n^2) O(n^2)
class Solution {
public:
int countSubstrings(string s) {
// dp[i][j] 表示闭区间[i,j]的子串是否为回文子串
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;
}
};
// 双指针 O(n^2) O(1)
class Solution {
public:
int countSubstrings(string s) {
int result = 0;
for (int i = 0; i < s.size(); i++) {
result += extend(s, i, i, s.size());
result += extend(s, i, i + 1, s.size());
}
return result;
}
int extend(const string& s, int i, int j, int n) {
int res = 0;
while ( i >= 0 && j < n && s[i] == s[j]) {
i--;
j++;
res++;
}
return res;
}
};
516. 最长回文子序列
心得
- 注意回文子序列和回文子串区别,子串是连续的,子序列是非连续的
题解
- 此时可以dp[i][j]直接表示最长长度,还是考虑区间[i, j] ,考虑相等不等对于长度的叠加,注意遍历顺序由递推推出遍历顺序,同时初始化值
class Solution {
public:
int longestPalindromeSubseq(string s) {
// dp[i][j]闭区间[i, j]的最长回文子序列
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++) { // 为了保证j - 1有意义
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];
}
};