动态规划 & 最长公共子串算法(LCS)

求最长公共子串可以先求最长公共子串的长度,并且记录那些公共子串字符的长度以及字符,然后通过回溯可以找到所有的公共子串。

下面是求最长公共子串长度的动态规划方法。

1:决策,我们在最后一步需要做的决策是,是否要将A[n],B[m]加入公共子串序列中。

2:由 1 可知,若以DP[i][j]表示A[1..i] 与 B[1..j]的最长公共子串的长度,那么可以得到

  (1) 若A[i] == B[j]  (即作出决策,将A[i],B[i]都加入公共子串)

      DP[i][j] = DP[i - 1][j - 1] + 1

  (2) 若A[i] != B[j]  (即将A[i] B[i] 最多一个加入公共子串,具体值由DP[i-1][j] 和DP[i][j-1]确定

      DP[i][j] = max(DP[i-1][j],DP[i][j-1]

至此,得到动态规划的第一个特点,最优子结构,即每次对问题的求解(对DP[i][j]的求解),都可以转换为对最优子结构的处理(即DP[i-1][j],DP[i][j-1],DP[i-1][j-1],这三种情况所包含的子串都是最优子结构,所以对 DP[i][j] 的求解就可以变成对上面三种情况所包含的 "当前最长子串" 的长度求解)

3: 求每一个DP[i][j],由于每次求DP[i][j],都需要重复求解DP[i-1][j-1],所以可以用一个矩阵记录每个DP[i][j]的值,该矩阵就是 备忘录

这里得到动态规划的第二特点,子问题重复求解,不同于 诸如二叉树遍历的 递归算法,每次都在遍历之前从未遍历的节点,   也不同于 贪心算法 ,每次都对不变化的子情况 调用贪心策略

4: 对备忘录进行优化,以及加入回溯信息

由于我们的问题是求最长子串,所以我们并不关心遍历完A,B串之前的那些 "当前最长子串"

所以可以在求得D[i][1..n]之后,用D[i][1..n]覆盖掉之前的D[i-1][1..n]

使得备忘录由 矩阵 变为 一维数组 ,空间复杂度由O( m * n),变成 O( min(m,n) )

加入回溯信息:

最常规的方法是每次求最大长度的时候,把整个已经得到的前缀都保存起来,但是那样会浪费大量的存储空间,还可能使得对 备忘录 的优化变得毫无意义

可以发现

我们在求子串的最大长度的过程中,是知道在什么时候(即A[i]==B[j] 时,并且此时的子串长度为DP[i][j]),在子串中加入了哪个字符

时间: 2024-10-26 21:21:16

动态规划 & 最长公共子串算法(LCS)的相关文章

动态规划算法之:最长公共子序列 & 最长公共子串(LCS)

1.先科普下最长公共子序列 & 最长公共子串的区别: 找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的.而最长公共子序列则并不要求连续. 2.最长公共子串 其实这是一个序贯决策问题,可以用动态规划来求解.我们采用一个二维矩阵来记录中间的结果.这个二维矩阵怎么构造呢?直接举个例子吧:"bab"和"caba"(当然我们现在一眼就可以看出来最长公共子串是"ba"或"ab") b a b c 0 0 0 a 0 1

【实习记】2014-08-29算法学习Boyer-Moore和最长公共子串(LCS)

昨天的问题方案一:寻找hash函数,可行性极低.方案二:载入内存,维护成一个守护进程的服务.难度比较大.方案三:使用前5位来索引,由前3位增至前5位唯一性,理论上是分拆记录扩大100倍,但可以就地利用mysql,最易行.方案四:使用方案三,但增加一个表以减少冗余,但代价新开一个表,并且每次查询都select join两个表. 研究了 求最长公共子串问题,顺便研究了字符串匹配 字符串匹配的Boyer-Moore算法http://www.ruanyifeng.com/blog/2013/05/boy

动态规划——最长公共子串

引入: 最长公共子序列常用于解决字符串的相似度问题. 最长公共子序列(Longest Common Subsequence,LCS)与最长公共字串(Longest Common Substring):子串是串的一个连续的部分,子序列则是从不改变序列顺序,而从序列中去掉任意多个元素而获得的新的序列:也就是说,子串中字符的位置一定是连续的,而子序列不一定连续. a  not the 之一(得到的未必就是唯一的那个最长公共子串,只有长度是唯一的) --其余字符串问题,待续 解决方案: 1.穷举法(Br

《算法导论》读书笔记之动态规划—最长公共子序列 & 最长公共子串(LCS)

From:http://my.oschina.net/leejun2005/blog/117167 1.先科普下最长公共子序列 & 最长公共子串的区别: 找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的.而最长公共子序列则并不要求连续. 2.最长公共子串 其实这是一个序贯决策问题,可以用动态规划来求解.我们采用一个二维矩阵来记录中间的结果.这个二维矩阵怎么构造呢?直接举个例子吧:"bab"和"caba"(当然我们现在一眼就可以看出来最长公共子串是

算法作业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的

算法系列笔记6(动态规划—最长公共子序列/串lcs)

子序列要求元素顺序一致就可以了,而字串必须是连续的.如ABCBDAB与BDCABA两个字符串,最长公共子序列有BCBA.BDAB和BCAB, 而最长公共字串只有AB和BD<连续>.当然这里的求解只求一个,但通常是这样直接说求最长公共子串,子序列,准确的应该是之一. 最长公共子序列 法一:穷举法 检查字符串x所有字序列,共有2^m个,检查它是否在y字符串中出现,每个需要O(n),时间复杂度为指数级的. 法二:动态规划(DP) 将两个字符串x[1-m]和y[1-n]放在x轴和y轴方向上便得到一个二

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

最长公共子序列也是动态规划中的一个经典问题. 有两个字符串 S1 和 S2,求一个最长公共子串,即求字符串 S3,它同时为 S1 和 S2 的子串,且要求它的长度最长,并确定这个长度.这个问题被我们称为 最长公共子序列问题. 与求最长递增子序列一样,我们首先将原问题分割成一些子问题,我们用 dp[i][j]表示 S1 中前 i 个字符与 S2 中前 j 个字符分别组成的两个前缀字符串的最 长公共子串长度. 显然的,当 i. j 较小时我们可以直接得出答案,如 dp[0][j]必 等于 0.那么,

动态规划--最长公共子串

最长公共子串也是一个动态规划的问题,先求出子问题的解,然后才能求出最优解. 首先我们来看设X = <x1, x2, ..., xm>, Y= <y1, y2, ..., yn>,设C[i][j]为串 Xi 和 Yj 的最长公共子串长度,则 C[i][j]  =  C[i-1][j-1] +1,  Xi == Yj C[i][j]  =  0,  Xi != Yj 申请一个m*n的数组,同时计算出该数组对应位置的数值,找出最大值,则为X 和 Y最长公共子串. 代码如下: 1 // L

最长公共子串(LCS)

找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的.其实这又是一个序贯决策问题,可以用动态规划来求解.我们采用一个二维矩阵来记录中间的结果.这个二维矩阵怎么构造呢?直接举个例子吧:"bab"和"caba"(当然我们现在一眼就可以看出来最长公共子串是"ba"或"ab") b a b c 0 0 0 a 0 1 0 b 1 0 1 a 0 1 0 我们看矩阵的斜对角线最长的那个就能找出最长公共子串. 不过在二维矩阵上找最