最长公共子序列

来源:互联网 发布:淘宝网天天特价连衣裙 编辑:程序博客网 时间:2024/06/07 18:04

最长公共子序列

最长公共子序列与最长公共子串的区别在于最长公共子序列不要求在原字符串中是连续的,比如ADE和ABCDE的最长公共子序列是ADE。

我们用动态规划的方法来思考这个问题如是求解。首先要找到状态转移方程:

符号约定,C1是S1的最右侧字符,C2是S2的最右侧字符,S1‘是从S1中去除C1的部分,S2’是从S2中去除C2的部分。

LCS(S1,S2)等于下列3项的最大者:

(1)LCS(S1,S2’)

(2)LCS(S1’,S2)

(3)LCS(S1’,S2’)–如果C1不等于C2; LCS(S1’,S2’)+C1–如果C1等于C2;

边界终止条件:如果S1和S2都是空串,则结果也是空串。

下面我们同样要构建一个矩阵来存储动态规划过程中子问题的解。这个矩阵中的每个数字代表了该行和该列之前的LCS的长度。与上面刚刚分析出的状态转移议程相对应,矩阵中每个格子里的数字应该这么填,它等于以下3项的最大值:

(1)上面一个格子里的数字

(2)左边一个格子里的数字

(3)左上角那个格子里的数字(如果 C1不等于C2); 左上角那个格子里的数字+1( 如果C1等于C2)

举个例子:

   G  C  T  A

  0  0  0  0  0

G  0  1  1  1  1

B  0  1  1  1  1

T  0  1  1  2  2

A 0  1  1  2  3

填写最后一个数字时,它应该是下面三个的最大者:

(1)上边的数字2

(2)左边的数字2

(3)左上角的数字2+1=3,因为此时C1==C2

所以最终结果是3。

public static void longString(String a,String b){        //创建一个数组        int[][] num = new int[a.length()+1][b.length()+1];        for(int i=1;i<a.length()+1;i++){            for(int j =1;j<b.length()+1;j++){                if(a.charAt(i-1) == b.charAt(j-1)){                    num[i][j] = num[i-1][j-1]+1;                }else{                    num[i][j] = Math.max(num[i-1][j], num[i][j-1]);                }            }        }        StringBuffer stringBuffer = new StringBuffer();        int length1=a.length(),length2 = b.length();        while( length1 > 0 && length2 > 0 ){            if(a.charAt(length1-1) == b.charAt(length2-1)){                stringBuffer.append(a.charAt(length1-1));                length1 --;                length2 --;            }else if(num[length1][length2-1]>=num[length1-1][length2]){                length2 --;            }else {                length1 --;            }        }        System.out.println("最长公共子序列"+stringBuffer.reverse().toString());    }public static void main(String[] args) {        String bString = "qetuo";        String aString = "qwetyui";        longString(aString, bString);    }
原创粉丝点击