代码随想录算法训练营
Day46 代码随想录算法训练营第 46 天 | 647. 回文子串 516.最长回文子序列
目录
前言
LeetCode 647. 回文子串
LeetCode 516.最长回文子序列
一、LeetCode 647. 回文子串
1.题目链接
2.思路
(1)dp数组含义:
dp[i][j] 表示区间[i,j]是否为回文子串
(2)状态转移
1)如果s[i]不等于s[j],一定不是回文子串
2)如果s[i]等于s[j]
① i与j的差值小于等于1:类似于a或者aa,是回文子串
② i与j的差值大于1:要判断[i+1,j-1]是不是回文子串
例如:cabac,确定两边都是c ,要判断aba是不是回文子串
(3)初始化:
初始化为false
(4)遍历顺序
1)由于通过dp[i + 1][j - 1]确定dp[i][j] ,所以:
先确定大的i值,i要从后向前遍历;
先确定小的j值,j要从前向后遍历
2)由于闭区间[i,j]:i<=j
3.题解
class Solution {
public:
int countSubstrings(string s) {
int n = s.size();
vector<vector<bool>> dp(n, vector<bool>(n, false));
int res = 0;
for (int i = n - 1; i >= 0; i--) {
for (int j = i; j < n; j++) {
if (s[i] == s[j]) {
if (abs(i - j) <= 1) {
dp[i][j] = true;
res++;
} else {
if (dp[i + 1][j - 1]) {
dp[i][j] = true;
res++;
}
}
}
}
}
return res;
}
};
二、LeetCode516.最长回文子序列
1.题目链接
2.思路
(1)dp[i][j]:
[i,j]区间最长回文子序列长度
(2)状态转移
1)如果s[i]等于s[j]:
① 如果 i=j 那么区间内最长回文子序列长度为1
② 如果 |i-j|=1那么区间内最长回文子序列长度为2
③ 其他情况,s[i]和s[j]加入[i+1,j-1]最长回文子序列,长度+2
2)如果s[i]不等于s[j]:
s[i]或s[j]加入[i+1,j-1]最长回文子序列,可能都不加
(3)初始化:初始化为0
(4)遍历:
从后向前遍历i,从i开始从前向后遍历j
3.题解
class Solution {
public:
int longestPalindromeSubseq(string s) {
int n = s.size();
vector<vector<int>> dp(n, vector<int>(n, 0));
for (int i = n - 1; i >= 0; i--) {
for (int j = i; j < n; j++) {
if (s[i] == s[j]) {
if (i == j)
dp[i][j] = 1;
else if (abs(i - j) == 1)
dp[i][j] = 2;
else
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][n - 1];
}
};