• 算法作业6 动态规划


    问题描述:Given 2 sequences, X = x1,...,xm and Y = y1,...,yn, find a common subsequence whose length is maximum. Subsequence need not be consecutive, but must be in order.

    程序思路:

    使用递归的思路可以解决这个问题。设输入的两个子串为X[0…m - 1]和Y[0…n - 1],L(X[0…m - 1], Y[0…n - 1])为X和Y的最长公共子串长度。分两种情况:

    1. 若子串最后一个字符匹配(即X[m – 1] == Y[n – 1]),则

    L(X[0…m - 1], Y[0…n - 1])= 1 + L(X[0…m - 2], Y[0…n - 2])

    2. 若子串最后一个字符不匹配(即X[m – 1] != Y[n – 1]),则

    L(X[0…m - 1], Y[0…n - 1]) = Max( L(X[0…m - 2], Y[0…n - 1]), L(X[0…m - 1], Y[0…n - 2]))

    但是递归的情况下,很多子情况会重复计算多次,因此可以使用动态规划来优化,这里可以使用画表格的方法来记录下子问题的解,供后面计算使用。这里的表格记录最长公共子串的长度。

    例如:”ABCFGR” 和”ACKWGR”的最长公共子串表为

    右下角的值就是两个子串的最长公共子串长度。

    如果需要输出两个子串的最长公共子串,则需要额外的空间把每个字符存起来。步骤如下:

    1. 构造最长公共子串长度表L[][];
    2. 构造一个长为L[m][n]的string s;
    3. 从L[m][n]这个位置开始遍历L[][],直到m或者n为0,对于L[][]中的每个元素L[i][j],

    a)    若X[i - 1] == Y[j - 1],即这个字符是最长公共子串的一个字符,放在s的末尾,往左上方移动一格,即i – 1,j – 1,继续遍历。

    b)    若不等,则在表格左边或者上方选择一个较大值,移动一格,即i – 1或者j – 1,继续遍历。

    根据上面的例子,给出遍历路径:

    所以”ABCFGR” 和”ACKWGR”的最长公共子串为”ACGR”。

    算法伪代码:

     1 //LCS算法
     2 //输入:子串X,子串Y,X的长度m,Y的长度n
     3 //输出:最长公共子串
     4 LCS(X[], Y[], m, n)
     5 Begin
     6 Create L[m + 1][n + 1]
     7 for each i from 0 to m do
     8        for each j from 0 to n do
     9               if i == 0 or j == 0
    10                      L[i][j] = 0
    11               Else if X[i – 1] == Y[j – 1]
    12                      L[i][j] = L[i – 1][j – 1] + 1
    13               Else
    14                      L[i][j] = max(L[i – 1][j], L[i][j – 1])
    15 Create char c[L[m][n]]
    16 For L[m][n] to L[0][p] or L[q][0]
    17        If X[i - 1] == Y[j – 1]
    18               Push this char to c
    19               Skip to left up
    20        Else
    21               Skip to left or up which is larger
    22 End

    算法性能分析:

    这个算法主要做的事情是,建立最长公共子串表,然后遍历这个表。表的建立需要一个一个填写表项,因此复杂度为O(mn)。

    补充一下,之前一直没有考虑最长公共子串不唯一的问题。我们的算法的确能够找到一个最长公共子串,但是如果要把所有的串输出,在步骤二中必须分情况讨论,把中间结果压栈,具体细节有空再补充。

  • 相关阅读:
    TS
    多点触摸的操作与图片放大缩小
    动画 -- 按钮 -- 左右晃动
    动画 -- 按钮 --- 从无到有(中心)
    动画 -- 点击按钮 -- 向右下方移动
    动画 -- 点击按钮 -- 顺时针旋转一圈
    动画 -- 点击按钮
    动画 -- ListView列表item逐个出来(从无到有)
    动画 --- 添加 和 移除 按钮
    动画-- 按钮按序列(从小到大)显示
  • 原文地址:https://www.cnblogs.com/banyu/p/4987921.html
Copyright © 2020-2023  润新知