LCS最長公共子序列——動態規劃

給定兩個字符序列X{x1,x2,x3,...,xm}Y{y1,y2,...,yn}

設最長公共子序列爲Z{z1,z2...zk},那麼,以下結論成立:

C(i, j)的遞推方程如下:

C(x, y) = 0 ,i=0,j=0

= C(i-1 ,j-1)+1i,j>0 , xi = yj

= max{ C(i-1 , j) , C(i , j-1)}i,j>0 , xi!= yj

網上的一張圖比較清晰地反映尋找過程,其實基本很多算法書都是參考這樣的圖~~~

090309172.jpg

public static int Length(char [] strX,char[]strY){
        final int MAX = 1000;
        int [][] C = new int[MAX][MAX];
        int [][] B = new int[MAX][MAX];
        int m = strX.length+1;
        int n = strY.length+1;
        for(int i = 0 ; i < m ; i++){
            C[i][0] = 0;//初始化第一行
        }
        for(int j = 0 ; j < n ; j++){
            C[0][j] = 1;//初始化第一列
        }
        for(int i = 1 ; i < m ; i++){
            for(int j = 1 ; j < n ; j++){
                //i-1是因爲字符數組從第0個字符開始比較
                if(strX[i-1]==strY[j-1]){
                    C[i][j] = C[i-1][j-1]+1;
                    B[i][j] = 1;//C[i][j]從C[i-1][j-1]得到
                }else if(C[i-1][j] >= C[i][j-1]){
                    C[i][j] = C[i-1][j];
                    B[i][j] = 2;//從C[i-1][j]得到
                }else{
                    C[i][j] = C[i][j-1];
                    B[i][j] = 3;//從C[i][j-1]得到
                }
            }
        }
        return C[m-1][n-1];
    }
//在實際的算法運行中,可以將B數組刪去,可以用C[i-1][j-1]保存B[i][j]的值
  public static void PrintCS(int[][]B,char []X, int i, int j){
        if(i==0 || j==0) return ;
        if(B[i][j] == 1){
            PrintCS(B,X,i-1,j-1);
            System.out.print(X[i-1]);
        }else if(B[i][j] == 2){
            PrintCS(B,X,i-1,j);
        }else{
            PrintCS(B,X,i,j-1);
        }
    }
PrintCS(B,strX,m-1,n-1);//注意m-1和n-1,因爲m和n都等於length+1

B[i][j]=1,C[i][j]C[i-1][j-1]得到;B[i][j]=2,C[i-1][j]得到;B[i][j]=3,從C[i][j-1]得到


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章