LCS

Posted wqkant

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LCS相关的知识,希望对你有一定的参考价值。

LCS具有最优子结构

令 X=<x1,x2,...,xm> 和 Y=<y1,y2,...,yn> 为两个序列,Z=<z1,z2,z3,...,zk>XY的任意LCS。则

如果xm=yn,则zk=xm=ynZk1Xm1Yn1的一个LCS。 
如果xmyn,那么zkxm,意味着ZXm1Y的一个LCS。 
如果xmyn,那么zkyn,意味着ZXYn1的一个LCS。

  从上述的结论可以看出,两个序列的LCS问题包含两个序列的前缀的LCS,因此,LCS问题具有最优子结构性质。在设计递归算法时,不难看出递归算法具有子问题重叠的性质。 
  设C[i,j]表示XiYj的最长公共子序列LCS的长度。如果i=0j=0,即一个序列长度为0时,那么LCS的长度为0。根据LCS问题的最优子结构性质,可得如下公式:

 

 代码实现

public class Main{
    static final int MAX=1000+1;
    private static final int C[][]=new int[MAX][MAX];
    private static final char B[][]=new char[MAX][MAX];
    private static int RecursiveLCS(char[] X,char Y[],int i,int j){
        if(i==0||j==0) return 0;
        if(C[i][j]>0) return C[i][j];
        if(X[i-1]==Y[j-1]){        
            C[i][j]=RecursiveLCS(X,Y,i-1,j-1)+1;
            
        }else{
            C[i][j]=Math.max(RecursiveLCS(X,Y,i-1,j),RecursiveLCS(X,Y,i,j-1));        
        }
        return C[i][j];
    }
    private static void LCS(char[] X,char Y[]){
        int XLen=X.length;
        int YLen=Y.length;
        for(int i=1;i<=XLen;i++){
            for(int j=1;j<=YLen;j++){
                if(X[i-1]==Y[j-1]){
                    C[i][j]=C[i-1][j-1]+1;
                    B[i][j]=\'↖\';
                }else if(C[i-1][j]>=C[i][j-1]){
                    C[i][j]=C[i-1][j];
                    B[i][j]=\'↑\';
                }else{
                    C[i][j]=C[i][j-1];
                    B[i][j]=\'←\';
                }
            }
        }
    }
//    private static void PrintLCS(char[] X,int i,int j){
//        if(i==0||j==0) return;
//        if(B[i][j]==\'↖\'){
//            PrintLCS(X,i-1,j-1);
//            System.out.print(X[i-1]);
//        }else if(B[i][j]==\'↑\'){
//            PrintLCS(X,i-1,j);
//        }else{
//            PrintLCS(X,i,j-1);
//        }
//    }
    private static void PrintLCS(char[] X,int i,int j){    
        int k=C[i][j];
        char [] S=new char[k];
        while(k>0){
            if(C[i][j]==C[i-1][j]){
                i--;
            }else if(C[i][j]==C[i][j-1]){
                j--;
            }else{
                S[--k]=X[i-1];
                i--;j--;
            }
        }
        System.out.println(S);
    }
    public static void main(String[] args){
        char [] X="ACCGGTCGAGTGCGCGGAAGCCGGCCGAA".toCharArray();
        char [] Y="GTCGTTCGGAATGCCGTTGCTCTGTAAA".toCharArray();
        RecursiveLCS(X,Y,X.length,Y.length);
        //LCS(X,Y);
        System.out.println(C[X.length][Y.length]);
        PrintLCS(X,X.length,Y.length);        
    }
}

 

 

以上是关于LCS的主要内容,如果未能解决你的问题,请参考以下文章

最长公共子序列(LCS),求LCS长度和打印输出LCS

LCS的数量

经典问题LCS(最大公共子串问题)C代码实现

LCS问题

Aizu2090LCS

已知一序列无重复元素,对LCS通过LIS进行优化