给定一个字符串s
,找到其中最长的回文子序列。可以假设s
的最大长度为1000
。
示例 1:
输入:
"bbbab"
输出:
4
一个可能的最长回文子序列为 "bbbb"。
示例 2:
输入:
"cbbd"
输出:
2
一个可能的最长回文子序列为 "bb"。
分析:
最小回文子串:子串是连续的。最小回文子序列:可以去掉几个字符。本题类似最小回文子串,采用动态规划,我们假设dp[ i ] [ j ]表示从S字符串中第i到j最长回文子序列的长度。那么状态转换方程为:
dp[i][j] = max{ dp[i+1][j], dp[i][j-1]} --S[i] !=S[j] 字符不相等,长度为两端最大值
dp[i][j] = dp[i+1][j-1]+2; --S[i] ==S[j] 字符相等,长度为内侧子串长度+2
代码:
import java.util.*;
/**
* @author: Mr.Hu
*/
public class Main{
public static void main(String[] args) {
Scanner sc =new Scanner(System.in);
System.out.println(longestPalindrome(sc.next()));
}
public static int longestPalindrome(String s) {
if (s.length()==0) return 0;
int dp[][]=new int[s.length()][s.length()]; //记录回文子序列长度
for (int i = 0; i < s.length(); i++) { //初始化长度为1和2的dp
dp[i][i]=1;
if (i<s.length()-1 ) {
dp[i][i+1]=1;
if (s.charAt(i)==s.charAt(i+1)) dp[i][i+1]=2;
}
}
for (int l = 3; l <= s.length(); l++) { //因为i+1 和j-1 所以长度得从3开始。
for (int i = 0; i+l-1 < s.length(); i++) {
int j=i+l-1;
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][s.length()-1];
}
}