算法导论---学习笔记07

来源:互联网 发布:道士下山 知乎 编辑:程序博客网 时间:2024/05/13 11:00

动态规划求解最长公共子序列(LCS)

首先,子序列和子串是不一样的。子串是连续的,而子序列中的元素组成可以是不连续的,但元素的位置下标一定是递增的。

子问题的递归结构

计算最优值

    Procedure LCS_LENGTH(X,Y);      begin        m:=length[X];        n:=length[Y];        for i:=1 to m do c[i,0]:=0;        for j:=1 to n do c[0,j]:=0;        for i:=1 to m do          for j:=1 to n do            if x[i]=y[j] then              begin                c[i,j]:=c[i-1,j-1]+1;                b[i,j]:="↖";              end            else if c[i-1,j]≥c[i,j-1] then              begin                c[i,j]:=c[i-1,j];                b[i,j]:="↑";              end            else              begin                c[i,j]:=c[i,j-1];                b[i,j]:="←"              end;        return(c,b);      end;  

首先从b[m,n]开始,沿着其中的箭头所指的方向在数组b中搜索。

  • 当b[i,j]中遇到"↖"时(意味着xi=yi是LCS的一个元素),表示Xi与Yj的最长公共子序列是由Xi-1与Yj-1的最长公共子序列在尾部加上xi得到的子序列;
  • 当b[i,j]中遇到"↑"时,表示Xi与Yj的最长公共子序列和Xi-1与Yj的最长公共子序列相同;
  • 当b[i,j]中遇到"←"时,表示Xi与Yj的最长公共子序列和Xi与Yj-1的最长公共子序列相同。

    这种方法是按照反序来找LCS的每一个元素的。由于每个数组单元的计算耗费Ο(1)时间,算法LCS_LENGTH耗时Ο(mn)。

2.4、构造最长公共子序列

    下面的算法LCS(b,X,i,j)实现根据b的内容打印出Xi与Yj的最长公共子序列。通过算法的调用LCS(b,X,length[X],length[Y]),便可打印出序列X和Y的最长公共子序列。

    Procedure LCS(b,X,i,j);      begin        if i=0 or j=0 then return;        if b[i,j]="↖" then          begin            LCS(b,X,i-1,j-1);            print(x[i]); {打印x[i]}          end        else if b[i,j]="↑" then LCS(b,X,i-1,j)                             else LCS(b,X,i,j-1);      end;   

在算法LCS中,每一次的递归调用使i或j减1,因此算法的计算时间为O(m+n)。

例如,设所给的两个序列为X=<A,B,C,B,D,A,B>和Y=<B,D,C,A,B,A>。由算法LCS_LENGTH和LCS计算出的结果如下图所示:


0 0
原创粉丝点击