码迷,mamicode.com
首页 > 编程语言 > 详细

算法作业6 动态规划 - 最长公共子串问题

时间:2015-11-23 13:13:45      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:

问题描述: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”。

 

算法伪代码:

//LCS算法

//输入:子串X,子串Y,X的长度m,Y的长度n

//输出:最长公共子串

LCS(X[], Y[], m, n)

Begin

Create L[m + 1][n + 1]

for each i from 0 to m do

       for each j from 0 to n do

              if i == 0 or j == 0

                     L[i][j] = 0

              Else if X[i – 1] == Y[j – 1]

                     L[i][j] = L[i – 1][j – 1] + 1

              Else

                     L[i][j] = max(L[i – 1][j], L[i][j – 1])

Create char c[L[m][n]]

For L[m][n] to L[0][p] or L[q][0]

       If X[i - 1] == Y[j – 1]

              Push this char to c

              Skip to left up

       Else

              Skip to left or up which is larger

end

 

算法性能分析:

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

算法作业6 动态规划 - 最长公共子串问题

标签:

原文地址:http://www.cnblogs.com/banyu/p/4987921.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!