动态规划-最长子序列求解-JAVA实现

【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*/

}

时间原因,可能有许多纰漏,望指出!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值