【2015/7/1】
动态规划-最长子序列求解 java实现
参考《算法导论》动态规划章节
文本数据格式:共两行,每行一个字符串序,起始标号1&2,每个字符之间用空格分隔
Eg: 1 A C D R F W Q C D
2 W E R T F D A C F D
数据读取存储可用数组也可用ArrayList实现
结果输出:直接打印到屏幕
记录表C:求长度
记录表b:记录选择方向
以上量表用一个单独的class记录
最优子结构递归表达式:
两个序列X,Y
1、若X[i] = Y[j],则c[i,j] = c[i -1][j - 1] + 1;
2、若X[i] \= Y[j],c[i,j] = max(c[i -1,j],c[i][j -1]).
以下为具体代码实现,易混淆处已加注释
package Test.LCS;
public class Chart {
public static final int SIZE = 100;
public static int[][] c = new int[SIZE][SIZE];
/*记录前缀的LCS长度--定义为静态对象*/
public static String[][] b = new String[SIZE][SIZE];
/*记录每一步时的选择方向*/
public void initialize(){/*初始化静态对象*/
for(int i = 0; i < SIZE; i ++){
c[i][0] = 0;
}
/*注意:此处不是嵌套循环,而是两个循环,
相当于把表格第一行与第一列初始化为零*/
for(int j = 0; j < SIZE; j ++){
c[0][j] = 0;
}
}
}
以下为主类:(ArrayList存数据)
package Test.LCS;
import java.io.*;
import java.util.*;
/*整体思路:先求LCS的长度,再逆序得到LCS*/
public class GetLCS {
public static void main(String[] args) throws IOException{
/*从文本读入两个序列----用Arraylist实现*/
BufferedReader newLine = new BufferedReader(new FileReader("LCS.txt"));
String temp1 = newLine.readLine();
String temp2 = newLine.readLine();
/*注:空格*/
String[] temp3 = temp1.split(" ");
String[] temp4 = temp2.split(" ");
ArrayList<String> firstSeqc = new ArrayList<String>();
ArrayList<String> secondSeqc = new ArrayList<String>();
/*注:此处i的范围限制*/
for(int i = 0; i < temp3.length; i ++){
firstSeqc.add(temp3[i]);
}
for(int j = 0; j < temp4.length; j ++){
secondSeqc.add(temp4[j]);
}
LCS_LENGTH(firstSeqc,secondSeqc);
}
/*求出LCS的长度,用c数组保存,同时用b数组保存选择最优解时每一步的方向*/
public static void LCS_LENGTH(ArrayList<String> X,ArrayList<String> Y){
Chart myChart = new Chart();
myChart.initialize();
for(int i = 1; i < X.size(); i ++){
for(int j = 1; j < Y.size(); j ++){
if( Y.get(j).compareTo(X.get(i)) == 0 ){/*走对角线*/
Chart.c[i][j] = Chart.c[i - 1][j -1] + 1;
Chart.b[i][j] = "upLeft";
}else if(Chart.c[i - 1][j] >= Chart.c[i][j - 1]){ /*向下走*/
Chart.c[i][j] = Chart.c[i - 1][j];
Chart.b[i][j] = "up";
}else{ /*向右走*/
Chart.c[i][j] = Chart.c[i][j - 1];
Chart.b[i][j] = "left";
}
}/*for--j*/
}/*for--i*/
/*注意:传送长度为X.size() - 1*/
printLCS(X,X.size() - 1,Y.size() - 1);
}/*LCS_LENGTH*/
/*回溯打印*/
public static void printLCS(ArrayList<String> X,int i,int j){
if(i == 0 || j == 0){
return;
}
if(Chart.b[i][j] == "upLeft"){
printLCS(X,i - 1,j - 1);
System.out.print(X.get(i));
}else if(Chart.b[i][j] == "up"){
printLCS(X,i - 1,j);
}else{
printLCS(X,i,j - 1);
}
}/*printLCS*/
}
附:数组存储数据方式
package Test.LCS;
import java.io.*;
import java.util.*;
public class LCS {
/*先求LCS的长度,再逆序得到LCS*/
public static void main(String[] args) throws IOException{
/*从文本读入两个序列*/
BufferedReader newLine = new BufferedReader(new FileReader("LCS2.txt"));
String temp1 = newLine.readLine();
String temp2 = newLine.readLine();
/*数组实现,但要求.txt文档输入序列时加入序号,且均以空格分隔
* eg: 1 A A C B D F
* 2 D D E F G A
* */
String[] firstSeqc = temp1.split(" ");
String[] secondSeqc = temp2.split(" ");
LCS_LENGTH(firstSeqc,secondSeqc);
}
/*求出LCS的长度,用c数组保存,同时用b数组保存选择最优解时每一步的方向*/
public static void LCS_LENGTH(String[] X,String[] Y){
Chart myChart = new Chart();
myChart.initialize();
for(int i = 1; i < X.length; i ++){
for(int j = 1; j < Y.length; j ++){
if(X[i].compareTo(Y[j]) == 0 ){/*走对角线*/
Chart.c[i][j] = Chart.c[i - 1][j -1] + 1;
Chart.b[i][j] = "upLeft";
}else if(Chart.c[i - 1][j] >= Chart.c[i][j - 1]){ /*向下走*/
Chart.c[i][j] = Chart.c[i - 1][j];
Chart.b[i][j] = "up";
}else{ /*向右走*/
Chart.c[i][j] = Chart.c[i][j - 1];
Chart.b[i][j] = "left";
}
}/*for--j*/
}/*for--i*/
printLCS(X,X.length - 1,Y.length - 1);
}/*LCS_LENGTH*/
public static void printLCS(String[] X,int i,int j){
if(i == 0 || j == 0){
return;
}
if(Chart.b[i][j] == "upLeft"){
printLCS(X,i - 1,j - 1);
System.out.print(X[i]);
}else if(Chart.b[i][j] == "up"){
printLCS(X,i - 1,j);
}else{
printLCS(X,i,j - 1);
}
}/*printLCS*/
}
时间原因,可能有许多纰漏,望指出!!!!