//动态规划
// class Solution {
// public int countSubstrings(String s) {
// char[] a = s.toCharArray();
// int len = a.length;
// //dp[i][j]代表区间[i, j]的回文子串数量
// boolean[][] dp = new boolean[len][len];
// int res = 0;
// //递推式dp[i][j] = true (a[i] == a[j] && (j - i) <= 1)
// //dp[i][j] = dp[i + 1][j - 1] (a[i] == a[j] && (j - i) > 1)
// //由递推式 逐列反向遍历(先j后i, j >= i因为连续)
// for (int i = len - 1; i >= 0; i--) {
// for (int j = i; j < len; j++) {
// if (a[i] == a[j] && (j - i <= 1 || dp[i + 1][j - 1])) {
// dp[i][j] = true;
// res++;
// }
// }
// }
// return res;
// }
// }
//双指针
class Solution {
public int countSubstrings(String s) {
//只有单数个和双数个的子串
char[] a = s.toCharArray();
int res = 0;
for (int i = 0; i < a.length; i++){
res += extend(a, i, i);
res += extend(a, i, i + 1);
}
return res;
}
//以center为中心向两边扩展
private int extend(char[] a, int c1, int c2) {
int sum = 0;
while (c1 >= 0 && c2 < a.length && a[c1] == a[c2]) {
sum++;
c1--;
c2++;
}
return sum;
}
}
![]()
class Solution {
public int longestPalindromeSubseq(String s) {
char[] a = s.toCharArray();
int len = a.length;
int[][] dp = new int[len][len];
//单独一个总是回文子序列
for (int i = 0; i < len; i++) dp[i][i] = 1;
for (int i = len - 1; i >= 0; i--) {
for (int j = i + 1; j < len; j++) {
if (a[i] == a[j]) {
dp[i][j] = dp[i + 1][j - 1] + 2;
} else {
//不相等则比较去掉a[i]或a[j]后哪个更大
dp[i][j] = Math.max(dp[i][j - 1], dp[i + 1][j]);
}
}
}
return dp[0][len - 1];
}
}
![]()
参考:programmercarl.com