1.回文子串 题647
①dp数组含义
判断回文子串可以用头元素和尾元素是否相等的方式,设dp[i] [j]为[i,j]子串是否为回文子串,是则为true,否为false。
②递推公式
若 s[i] == s[j] ,分三种情况:i == j,即只有一个元素,那么只有一个回文子串,结果为true;
j - i =1,比如aa,那么也是回文子串,结果为true;
j - i >=1, 就得看dp[i+1] [j-1]的结果,结果与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++) { //j必须大于等于i
if (s[i] == s[j]) {
if (j - i <= 1) { // 情况一 和 情况二
result++;
dp[i][j] = true;
} else if (dp[i + 1][j - 1]) { // 情况三
result++;
dp[i][j] = true;
}
}
}
}
return result;
}
};
2.最长回文子序列 题516
首先是子序列,然后才是回文,而子序列不一定是连续的。
①dp数组含义
跟回文子串差不多。[i] , j]的范围的回文子序列的长度。
②递推公式。
分两种情况,若s[i] == s[j],那么dp[i] [j] = dp[i+1] [j-1] + 2
若s[i] != s[j], 那么也有两种情况,由于回文子序列可以不连续,只取s[i] 或者 s[j] 也有可能构成回文子序列。故只取s[i] 为 dp[i] [j-1],只取s[j] 为dp[i+1] [j],取这两种情况的最大值。
③初始化
根据递推公式,i不断+1,j不断-1,不断向中间靠拢,直到i = j,而这里就是需要初始化的地方,i = j为一个元素,一个元素也为回文子序列,所以赋值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];
}
};