代码随想录Day46 | 647.回文子串,516.最长回文子序列
代码随想录Day46 | 647.回文子串,516.最长回文子序列
647.回文子串
-
dp[i][j]
定义:与其他动态规划题目不同,一般题目求什么,dp就定义为什么
这道题的dp定义为区间范围[i,j]的子串是否是回文子串
-
需要注意遍历顺序
需要用到
dp[i + 1][j - 1]
,即左下角元素且根据定义,j >= i
-
状态转移:
- 元素相等时
- 长度 <= 2,一定是回文,如 aa, a
- 长度 > 2时,若 [i+1, j-1] 范围,即除头尾元素外的内部子串为回文,则回文
- 元素不相等,则默认false
- 元素相等时
class Solution {
public int countSubstrings(String s) {
char[] chars = s.toCharArray();
int n = s.length();
// 定义:区间范围[i,j]的子串是否是回文子串
boolean[][] dp = new boolean[n][n];
int res = 0;
// 需要用到dp[i + 1][j - 1],即左下角元素,注意遍历顺序
for (int i = n - 1; i >= 0; i--) {
// j >= i
for (int j = i; j < n; j++) {
// 状态转移:
// 元素相等时
if (chars[i] == chars[j]) {
// 长度 <= 2,一定是回文,如 aa, a
if (j - i <= 1) {
res++;
dp[i][j] = true;
}
// 长度 > 2时
// 若 [i+1, j-1] 范围,即除头尾元素外的内部子串为回文,则回文
else if (dp[i + 1][j - 1]) {
res++;
dp[i][j] = true;
}
}
// 元素不相等,则默认false
}
}
return res;
}
}
516.最长回文子序列
dp[i][j]
定义:
回文问题,定义为s在[i,j]索引范围内的回文子序列个数
初始化:
单个字符时,是回文串
状态转移:
- 字符不匹配时,
dp[i][j] = Math.max(dp[i+1][j], dp[i][j-1])
取最大值 - 字符匹配时,
dp[i][j] = dp[i+1][j-1] + 2
长度加2
class Solution {
public int longestPalindromeSubseq(String s) {
int len = s.length();
char[] chars = s.toCharArray();
// dp[i][j]定义:
// s在[i,j]索引范围内的回文子序列个数
int[][] dp = new int[len][len];
for (int i = len - 1; i >= 0; i--) {
// 初始化
dp[i][i] = 1;
for (int j = i + 1; j < len; j++) {
// 状态转移:字符相等与不相等情况
if (chars[i] == chars[j])
dp[i][j] = dp[i+1][j-1] + 2;
else dp[i][j] = Math.max(dp[i+1][j], dp[i][j-1]);
}
}
return dp[0][len-1];
}
}