动态规划---最长公共子序列

来源:互联网 发布:plc模块化编程实例 编辑:程序博客网 时间:2024/06/12 00:45

看完算法导论关于这部分内容之后的总结:    

关于最长公共子序列问题:

                         给定两个子序列 X=<X1, X2, X3  , .... ,  Xm > ; Y=<Y1, Y2, Y3 ,..., Yn>,求X和Y长度最长的公共子序列。

解决方法:

                  首先先要了解LCS的最优子结构,令X=<X1, X2, X3  , .... ,  Xm > ; Y=<Y1, Y2, Y3 ,..., Yn>为两个子序列,Z = <Z1,Z2,... ,Zk>为X和Y的任意LCS。

                       1、如果 Xm = Yn , 则 Zk = Xm = Yn 且 Zk-1 是 Xm-1 和 Yn-1 的一个LCS;

                       2、如果 Xm ≠ Yn , 则 Zk ≠ Xm ,意味着 Z 是Xm-1和Y 的一个LCS;

                       3、如果 Xm ≠ Yn , 则 Zk ≠ Yn ,意味着 Z 是X和Yn-1 的一个LCS;


求解最长公共子序列主要用到以下公式

                                                  

 


伪代码分析

LCS_LENGTH(X,Y)
1、 m = X.length
2、 n = Y.length
3、 for i = 1 to m
4、      c[i,0] = 0    //c[][]计算表项
5、 for j =0 to m
6、      c[0,j] = 0   


7、 for i = 1 to m
8、 for j = 1 to n
9、      if Xi == Yj                            //先比较Xi 和 Yj 是否相等
10、        c[i,j] = c[i-1][j-1] + 1            //相等的话就将c[i,j]的值加上其上一个对角线元素的值
11、        b[i,j] = "↖"                       //并将当前单元格设置成"↖"
12、     elseif  c[i-1][j] ≥ c[i][j-1]         //Xi 和 Yj 不相等,则比较当前单元格上方和左方单元格的值
13、        c[i,j] = c[i-1][j]                  //如果上方单元格的值大于等于其左方单元格的值,则当前单元格设置成"↑"
14、        b[i][j] = "↑"
15、     else
16、        c[i][j] = c[i][j-1] 
17、        b[i][j] = "←"                      //否则设置成"←"
18、return c and b


根据以上伪代码构造出的表


执行4,5行后得到下面这个表:

 j0123456i YjBDCABA0Xi00000001A0      2B0      3C0      4B0      5D0      6A0      7B0      
然后以行为主序开始扫描:


我们可以先找出 Xi == Yj 的单元格,标记它的值和箭头方向 。

当i = 1时,扫描第一行中为(A,A)的单元格,标记为↖,并执行c[i][j] = c[i-1][j-1] + 1;
                 其它的单元格按照12-17行的代码进行标记,如(X1,Y1) = (A,B),两者不相同,所以比较(X1,Y1)上方和左方的单元格的值。哪个的值大,箭头就指向哪个单元格,并将c[i][j]的值设置为c[i-1,j],c[i,j-1]中具有较大值的单元格的值。                j0123456i YjBDCABA0Xi00000001A0↑0↑0↑0↖1←1↖12B0      3C0      4B0      5D0      6A0      7B0           当 i = 2时,按照以上方法进行单元格赋值。

     。。。。

     最后得到以下表格:

      

 j0123456i YjBDCABA0Xi00000001A0↑0↑0↑0↖1←1↖12B0      3C0      4B0      5D0      6A0      7B0     


 j0123456i YjBDCABA0Xi00000001A0↑0↑0↑0↖1←1↖12B0↖1←1←1↑1↖2←23C0↑1↑1↖2←2↑2↑24B0↖1↑1↑2↑2↖3←35D0↑1↖2↑2↑2↑3↑36A0↑1↑2↑2↖3↑3↖47B0↖1↑2↑2↑3↖4

                                                  ↑

                                             


得到上面的表格之后,执行以下函数得到LCS


PRINT-LCS(b, X, X.length, Y.length)
1、if X.length==0 || Y.length == 0
2、    return;
3、if b[i,j] == "↖"
4、     PRINT-LCS(b, X, X.length-1, Y.length-1)
5、     print Xi
6、elseif b[i,j] == "↑"
7、     PRINT-LCS(b, X, X.length-1, Y.length)
8、else
9、     PRINT-LCS(b, X, X.length, Y.length-1)




 j0123456i YjBDCABA0Xi00000001A0↑0↑0↑0↖1←1↖12B0      3C0      4B0      5D0      6A0      7B0     
0 0
原创粉丝点击