• 动态规划———最长公共子序列(LCS)


    最长公共子序列+sdutoj2080改编:

    http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Contest/contestproblem/cid/2788/pid/2080

    传送门 https://blog.csdn.net/sunshine_pb/article/details/21820159 

    设序列X={x1,x2,…,xm}和Y={y1,y2,…,yn}的最长公共子序列为Z={z1,z2,…,zk},

    记:    Xk为序列X中前k个连续字符组成的子序列,

    Yk为序列Y中前k个连续字符组成的子序列,

               Zk为序列Z中前k个连续字符组成的子序列,

    显然有下式成立:

    (1)若xm=yn,则zk=xm=yn,且Zk-1是Xm-1和Yn-1的最长公共子序列;

    (2)若xm≠yn且zk≠xm,则Z是Xm-1和Y的最长公共子序列;

    (3)若xm≠yn且zk≠yn,则Z是X和Yn-1的最长公共子序列。

      可见,两个序列的最长公共子序列包含了这两个序列的前缀序列的最长公共子序列。

    要找出序列X={x1,x2,…,xm}和Y={y1,y2,…,yn}的最长公共子序列,可按下述递推方式计算:

    当xm=yn时,找出Xm-1和Yn-1的最长公共子序   列,然后在其尾部加上xm即可得到X和Y的最长公共子序列;

    当xm≠yn时,必须求解两个子问题:找出Xm-1和Y的最长公共子序列以及Xm和Yn-1  的最长公共子序列,这两个公共子序列中的较长

    者即为X和Y的最长公共子序列

      设L[i][j]表示子序列Xi和Yj的最长公共子序列的长度,可得如下动态规划函数:

    L[0][0] = L[i][0] = L[0][j] = 0           (1≤i≤m,1≤j≤n)

       L[i][j]只是记录子序列的长度,要打印得到XmYn具体的最长公共子序列,设二维表S[m+1][n+1],其中S[i][j]表示在计算L[i][j]的过程中的搜索状态,并且有:

    若S[i][j]=1,表明ai=bj,则下一个搜索方向是S[i-1][j-1];

    若S[i][j]=2,表明ai≠bj且L[i][j-1]≥L[i-1][j],则下一个搜索方向是S[i][j-1];

    若S[i][j]=3,表明ai≠bj且L[i][j-1]<L[i-1][j],则下一个搜索方向是S[i-1][j]。

    举例:序列X=(a,b,c,b,d,b),Y=(a,c,b,b,a,b, d, b,b),建立两个(m+1)×(n+1)的二维表L和表S,分别存放搜索过程中得到的子序列的长

    度和状态。

    下面代码为sdutoj2080改编代码:

     1 /* */
     2 # include <bits/stdc++.h>
     3 using namespace std;
     4 
     5 int CommonOrder( int len1, int len2, char x[], char y[], char z[]);
     6 int L[501][501];
     7 int S[501][501];
     8 int main()
     9 {
    10     char a[501], b[501], z[501];
    11     int i, t, len1, len2;
    12     while( gets(a) && gets(b) )
    13     {
    14         len1 = strlen(a);
    15         len2 = strlen(b);
    16         t = CommonOrder(len1, len2, a, b, z);
    17         printf("%d
    ", t);
    18         for( i=1; i<=t; i++ )
    19         {
    20             printf("%c%c", z[i], i==t?'
    ':' ');
    21         }
    22     }
    23     return 0;
    24 }
    25 
    26 int CommonOrder(int m, int n, char x[], char y[], char z[])
    27 {
    28     int j, i, k;
    29     for( j=0; j<=n; j++ )
    30     {
    31         L[0][j] = 0;
    32     }
    33     for( i=0; i<=m; i++ )
    34     {
    35         L[i][0] = 0;
    36     }
    37     for( i=1; i<=m; i++ )
    38     {
    39         for( j=1; j<=n; j++ )
    40         {
    41             if( x[i-1]==y[j-1] )
    42             {
    43                 L[i][j] = L[i-1][j-1]+1;
    44                 S[i][j] = 1;
    45             }
    46             else if( L[i][j-1]>=L[i-1][j] )
    47             {
    48                 L[i][j] = L[i][j-1];
    49                 S[i][j] = 2;
    50             }
    51             else
    52             {
    53                 L[i][j] = L[i-1][j];
    54                 S[i][j] = 3;
    55             }
    56         }
    57     }
    58     i = m;
    59     j = n;
    60     k = L[m][n];
    61     while( i>=0 && j>=0 )
    62     {
    63         if( S[i][j]==1 )
    64         {
    65             z[k] = x[i-1];
    66             k--;
    67             i--;
    68             j--;
    69         }
    70         else if( S[i][j]==2 )
    71         {
    72             j--;
    73         }
    74         else
    75         {
    76             i--;
    77         }
    78     }
    79     return L[m][n];
    80 }

    算法分析:在算法中,

    第一个for循环的时间性能是O(n);

    第二个for循环的时间性能是O(m);

    第三个循环是两层嵌套的for循环,其时间性能是O(m×n);

    第四个for循环的时间性能是O(k),而k≤min{m,n},所以,算法的时间复杂性是O(m×n)。

  • 相关阅读:
    ui自动化---select标签和浏览器等待
    ui自动化--鼠标操作ActionChains
    ui自动化---WebDriverApi接口
    ui自动化---CssSelector
    ui自动化--xpath
    html基础:jquery的ajax获取form表单数据
    grep使用方法
    VI打开和编辑多个文件的命令 分屏操作
    C语言编译器 cc 编译原理
    zabbix的mysql优化后的配置文件
  • 原文地址:https://www.cnblogs.com/wsy107316/p/10739258.html
Copyright © 2020-2023  润新知