刷算法题时遇到这道求最长回文子序列长度的题,因为其子序列不要求连续,跟普通求回文子序列不同,因此加以记录
- 题目描述:给定一仅由大小写字母组成的字符串,求其回文子序列的最大长度,回文子序列指正反读都一样的子序列,如madam。本题中大小写不敏感,即a和A相同。
- 输入描述:输入包含一行字符串,长度不超过300
- 输出描述:输出该字符串最长回文子序列的长度
- 输入样例:ABCdca
- 输出样例:5
- 提示:子序列不要求连续
方法一:二维动态规划
public class Question6_最长回文子序列_动态规划 {
public static void main(String[] args) {
String s=new Scanner(System.in).next();
String str=s.toLowerCase();
int n=str.length();
if(n==1){
System.out.println(1);
return;
}
int[][]dp=new int[n][n];
//单个字符的最长回文子序列长度为1
for(int i=0;i<n;i++)
dp[i][i]=1;
//第一层循环代表:两个字符之间的距离
for(int dist=1;dist<=n-1;dist++){
for(int i=0;i<n;i++)
for(int j=i+dist;j<n;j++){
/*这两个字符之间的最长回文长度
* 1.如果两个字符相同,则等于内部最大的+2
* 2.不相同,则和内部最大的相同*/
int innerLargest=1;
if(dist!=1){
for(int k=i+1;k<j;k++)
for(int t=k;t<j;t++){
if(dp[k][t]>innerLargest)
innerLargest=dp[k][t];
}
}
if(str.charAt(i)==str.charAt(j))
dp[i][j]=dp[j][i]=innerLargest+2;
else
dp[i][j]=dp[j][i]=innerLargest;
}
}
System.out.println(dp[0][n-1]);
}
}
方法二:递归
public class Question6_递归解法 {
public static void main(String[] args) {
String s=new Scanner(System.in).nextLine().toLowerCase();
System.out.println(subStrLen(s));
}
//递归计算最长回文子序列的长度
public static int subStrLen(String s){
if(s.length()==1)
return 1;
if(s.length()==2){
if(s.charAt(0)==s.charAt(1))
return 2;
else
return 0;
}
int maxSubStrLen=1;
for(int dist=1;dist<=s.length()-3;dist++){
for(int i=1;i<s.length()-1;i++){
for(int j=i+dist;j<s.length()-1;j++){
int record=subStrLen(s.substring(i,j+1));
if(record>maxSubStrLen)
maxSubStrLen=record;
}
}
}
if(s.charAt(0)==s.charAt(s.length()-1))
return 2+maxSubStrLen;
else
return maxSubStrLen;
}
}