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

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

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

                         给定两个子序列 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行后得到下面这个表:

 j0123456
i YjBDCABA
0Xi0000000
1A0      
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]中具有较大值的单元格的值。               

 j0123456
i YjBDCABA
0Xi0000000
1A0↑0↑0↑0↖1←1↖1
2B0      
3C0      
4B0      
5D0      
6A0      
7B0      
     当 i = 2时,按照以上方法进行单元格赋值。

     。。。。

     最后得到以下表格:

      

 j0123456
i YjBDCABA
0Xi0000000
1A0↑0↑0↑0↖1←1↖1
2B0      
3C0      
4B0      
5D0      
6A0      
7B0     



 j0123456
i YjBDCABA
0Xi0000000
1A0↑0↑0↑0↖1←1↖1
2B0↖1←1←1↑1↖2←2
3C0↑1↑1↖2←2↑2↑2
4B0↖1↑1↑2↑2↖3←3
5D0↑1↖2↑2↑2↑3↑3
6A0↑1↑2↑2↖3↑3↖4
7B0↖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)




 j0123456
i YjBDCABA
0Xi0000000
1A0↑0↑0↑0↖1←1↖1
2B0      
3C0      
4B0      
5D0      
6A0      
7B0     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值