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

算法伪代码:

//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)。

时间: 2024-10-05 04:27:33

算法作业6 动态规划 - 最长公共子串问题的相关文章

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

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

动态规划 & 最长公共子串算法(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 -

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

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

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

最长公共子串也是一个动态规划的问题,先求出子问题的解,然后才能求出最优解. 首先我们来看设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

[程序员代码面试指南]递归和动态规划-最长公共子串问题

题目描述 给定两个串,输出最长公共子串. 解题思路 维护dp[i][j],表示子串str1[0:i+1]与str2[0:j+1]的最长公共子串长度. 由dp[][]右下角开始,找公共子串. 代码 public class Solution{ private int[][] getDp(char[] str1,char[] str2){ int[][] dp=new int[str1.length][str2.length]; int temp=0; for(int i=0;i<str1.leng

每周一道算法题011:最长公共子串

问题: 求以下几组单词的最长公共子串的长度1.fish和fosh2.fish和hish3.fish和vista 思路: 可以用表格法,横纵坐标分别是两个单词,如果字符相同,就用左上角的数字加1,最后取表格中的最大值. 解答: php: <?php // 找出两个单词的最长公共子串 function findLongestSubString($word1, $word2) { $len1 = strlen($word1); $len2 = strlen($word2); $cell = array

算法导论之动态规划(最长公共子序列和最优二叉查找树)

动态规划师通过组合子问题的解而解决整个问题,将问题划分成子问题,递归地求解各子问题,然后合并子问题的解而得到原问题的解.和分治算法思想一致,不同的是分治算法适合独立的子问题,而对于非独立的子问题,即各子问题中包含公共的子子问题,若采用分治法会重复求解,动态规划将子问题结果保存在一张表中,避免重复子问题重复求解. 动态规划在多值中选择一个最优解,其算法设计一般分为4个步骤:描述最优解的结构:递归定义最优解的值:按自底向上的方式计算最优解的值:由计算出的结果构造一个最优解. 1)装配线调度 求解最快

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

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

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

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