问题描述:
给一个字符串,找出它的最长的回文子序列的长度。例如,如果给定的序列是“BBABCBCAB”,则输出应该是7,“BABCBAB”是在它的最长回文子序列。 “BBBBB”和“BBCBB”也都是该字符串的回文子序列,但不是最长的。
1)最优子结构
假设 X[0 ... n-1] 是给定的序列,长度为n. 让 L(0,n-1) 表示 序列 X[0 ... n-1] 的最长回文子序列的长度。
1. 如果X的最后一个元素和第一个元素是相同的,这时:L(0, n-1) = L(1, n-2) + 2 , 还以 “BBABCBCAB” 为例,第一个和最后一个相同,因此 L(1,n-2) 就表示蓝色的部分。
2. 如果不相同:L(0, n-1) = MAX ( L(1, n-1) , L(0, n-2) )。 以”BABCBCA” 为例,L(1,n-1)即为去掉第一个元素的子序列,L(0, n-2)为去掉最后一个元素。
package 最长回文子序列;
import java.util.Scanner;
public class test {
/**
* 计算个数的时候,比较适合自上而下计算;
* 但是求解具体的值,适合自下而上。
*/
//统计个数
// public static int lhc(int start,int end){
// if(start>=end)
// return 0;
// else{
// if(ch[start]==ch[end]){
// //他们之间最长子序列的长度加2
// return lhc(start+1,end-1)+2;
// }else{
// //判断是[start+1,end],[start,end-1]之间的序列长度
// return lhc(start+1,end)>lhc(start,end-1)?lhc(start+1,end):lhc(start,end-1);
// }
// }
// }
public void inti(int[][] lpsArray,int max){
for(int i=0;i<max;i++)
for(int j=0;j<max;j++)
lpsArray[i][j]=0;
}
public int max(int x,int y){
return x>y?x:y;
}
public char dir(int x,int y){
return x>y?'←':'↓';
}
//创建数组
public int[][] lps(char[] ch){
int[][] lpsArray = new int[ch.length][ch.length];
char[][] dirc = new char[ch.length+1][ch.length+1];
this.inti(lpsArray,ch.length);
//method 1.
/*
for(int i=0;i<ch.length;i++)
for(int j=i;j<ch.length;j++){
if(i==j)
lpsArray[i][j]=0;
else{
if(ch[i]==ch[j])
lpsArray[i][j]=1;
else
lpsArray[i][j]=0;
}
}
*/
//method 2.
for(int i=0;i<ch.length;i++)
lpsArray[i][i]=0;
for(int i=1;i<ch.length;i++){
int temp =0;
//开始计算ch[i]到ch[j]之间最长回文的个数
for(int j=0;j+i<ch.length;j++){
if(ch[j]==ch[j+i]){
temp = lpsArray[j+1][j+i-1]+2;
dirc[j][j+i]='√';
}else{
temp = max(lpsArray[j][i+j-1],lpsArray[j+1][j+i]);
dirc[j][j+i] = dir(lpsArray[j][i+j-1],lpsArray[j+1][j+i]);
}
lpsArray[j][i+j]=temp;
}
}
for(int i=0;i<ch.length;i++){
for(int j =0;j<ch.length;j++)
System.out.print(" "+dirc[i][j]+" ");
System.out.println();
}
this.showSeq(dirc,lpsArray,ch.length);
return lpsArray;
}
//输出序列
public void showSeq(char[][] dirc,int[][] lpsArray,int max){
int i = 0; int j = max-1;
while(lpsArray[i][j]!=0){
System.out.println(dirc[i][j]);
if(dirc[i][j]=='←'){
j--;
}else if(dirc[i][j]=='↓'){
i++;
}else{
System.out.println("i = "+i+" j="+j);
i++;
j--;
}
}
}
//正
public static void main(String[] args) {
test t = new test();
// TODO Auto-generated method stub
System.out.println("请输入任意的字符串");
Scanner s = new Scanner(System.in);
String str = s.next();
//将字符串变为char数组
char[] ch = new char[str.length()] ;
str.getChars(0, str.length(), ch,0);
//存储最优解
int[][] lps =t.lps(ch);
for(int i=0;i<ch.length;i++){
for(int j =0;j<ch.length;j++)
System.out.print(lps[i][j]+" ");
System.out.println();
}
}
}