回文子串和最长回文子序列都是比较经典的回文问题,而动态规划是解决这类问题的常用方法。本文将介绍如何使用动态规划解决这两个问题,并提供Java代码实现。
- 回文子串
1.1 问题描述
给定一个字符串,计算这个字符串中有多少个回文子串。
1.2 解法
定义dp[i][j]表示字符串从i到j是否为回文子串,如果是则dp[i][j]=true,否则为false。那么有以下递推式:
如果s[i] == s[j],且dp[i+1][j-1]为true,则dp[i][j]为true;
如果s[i] == s[j],且j-i<=2,则dp[i][j]为true;
否则dp[i][j]为false。
根据上述递推式,我们可以得到以下Java代码实现:
public int countSubstrings(String s) {
int n = s.length();
boolean[][] dp = new boolean[n][n];
int count = 0;
for (int i = n - 1; i >= 0; i--) {
for (int j = i; j < n; j++) {
if (s.charAt(i) == s.charAt(j) && (j - i <= 2 || dp[i + 1][j - 1])) {
dp[i][j] = true;
count++;
}
}
}
return count;
}
时间复杂度为O(n^2),空间复杂度为O(n^2)。
- 最长回文子序列
2.1 问题描述
给定一个字符串,找到其中最长的回文子序列。
2.2 解法
定义dp[i][j]表示字符串从i到j中最长回文子序列的长度。那么有以下递推式:
如果s[i] == s[j],则dp[i][j] = dp[i + 1][j - 1] + 2;
否则dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1])。
根据上述递推式,我们可以得到以下Java代码实现:
public int longestPalindromeSubseq(String s) {
int n = s.length();
int[][] dp = new int[n][n];
for (int i = n - 1; i >= 0; i--) {
dp[i][i] = 1;
for (int j = i + 1; j < n; j++) {
if (s.charAt(i) == s.charAt(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][n - 1];
}
时间复杂度为O(n^2),空间复杂度为O(n^2)。
总结:
回文子串和最长回文子序列都是使用动态规划解决的经典问题。使用动态规划可以求解这两个问题,并且时间复杂度和空间复杂度都为O(n^2)。