1. 程式人生 > >最長公共子序列(LCS)

最長公共子序列(LCS)

() 參考資料 ... void 表格 abc src size charat

最長公共子序列問題在算法導論中引申自確定DNA序列相似度的問題:給定兩個DNA序列S1和S2,尋找第三個序列S3,要求序列S3中的元素都來源於S1和S2,且在這三個序列中先後順序相同,但在S1和S2中不要求連續,如果找到這樣的S3序列越長,可以認為S1和S2相似度越高。

問題描述:

給定兩個序列X=<x1,x2,x3...xm>和序列Y=<y1,y2,y3...yn>,求X和Y的最長公共子序列(LCS)。

分析:

分析其最優子結構性質需要從xm和yn入手,假設序列Z=<z1,z2,z3...zk>是序列X和Y的LCS

1、如果xm=yn,說明這兩個元素(實際上為同一個)必然在Z中,由於這兩個元素同時最為X和Y的最後一個元素,不難推斷,xm

=yn=zk必然成立,從Z中排除掉zk剩下的序列Zk-1=<z1,z2,z3...zk-1>必然是Xm-1和Yn-1的一個LCS。

2、如果xm!=yn,且zk!=xm,那麽xm必定不在Z中,但是yn有可能在Z中,因此可以判定,Z是Xm-1和Y的一個LCS。

3、如果xm!=yn,且zk!=yn,那麽yn必定不在Z中,但是xm有可能在Z中,因此可以判定,Z是X和Yn-1的一個LCS。

用C(i,j)表述Xi和Yi的LCS,其遞推式可以表示為:

技術分享

實際上可以看出對於每一個子問題C(i,j)的求解,不會用到太多的子子問題的解,字需要用到C(i-1,j-1)的解或者C(i-1,j)和C(i,j-1)的解。

也就是說求解當前表格的值只有其左方表格,上方表格和左上方的表格有關。

因此填充C(i,j)二維表格的順序應該是從左到右,從上到下的順序,這也是求解子問題的順序。

算法實現:

package agdp;

import java.util.Arrays;
public class LCS {
    public static int getLCS(String strA,String strB){
        int m = strA.length();
        int n = strB.length();
        int[][] aux = new int[m+1][n+1];//aux的第0行和第0列充當哨兵,無實際含義
for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (strB.charAt(j) == strA.charAt(i)) { aux[i+1][j+1] = aux[i][j]+1; }else { aux[i+1][j+1] = Math.max(aux[i+1][j], aux[i][j+1]); } } } return aux[m][n]; } public static void main(String[] args) { // TODO Auto-generated method stub // String strA = "ABCBDAB"; // String strB = "BDCABA"; String strA = "abfgkhrc"; String strB = "11a11bfgh33"; int result = getLCS(strA, strB); System.out.println(result); } }

參考資料:

算法導論.第十五章

最長公共子序列(LCS)