最长公共子序列(LCS)是经典的DP问题,求序列a[1...n], b[1..m]的LCS。

状态是DP[i][j],表示a[1..i],b[1..j]的LCS。

DP转移方程是

DP[i][j]=

  DP[i-1][j-1]+1,  a[i] == b[j]

  max{ DP[i][j-1], DP[i-1][j] },  a[i] != b[i] 

-------------------------------------------------------------------------------------------

时间复杂度O(N^2),空间复杂度0(N^2)。

使用滚动数组,可将空间复杂度降到 0(N)。

观察DP转移方程可看出,即使用滚动数组,也需要两个即DP[2][N],一个DP[N]行不通。

因为若只用一维数组DP[N]来保存状态,第一个式子要求从右向左更新,第二个式子要求从左向右更新。

------------------------------------------------------------------------------------

以上关于用滚动数组降低空间复杂度的论述有误

----------------------------------------------------------------

实际上只用一维数组DP[N]也可以。严格地说,上面的论述并没有错,若严格按照

DP[i][j]=

  DP[i-1][j-1]+1,  a[i] == b[j]

  max{ DP[i][j-1], DP[i-1][j] },  a[i] != b[i] 

来转移,一个DP[N]确实不够,但我们深入分析下一开始的论据--"第一个式子要求从右向左更新",

如果第一式也从左向右更新,那么在需要DP[i-1][j-1]时,它已被DP[i][j-1]覆盖

自然地,我们考虑把DP[i-1][j-1]单独存起来,问题就解决了。

---------------------------------------------------------------------------------------------------------------------------------------

还有一种思路,我们略微变通一下,将第一个转移方程改为

DP[i][j] = max{ DP[i-1][k] : k < j } +1

这样只要在从左到右更新时维护一个max{ DP[i-1][k] : k < j }

而DP[i-1][k] >= DP[i-1][k-1] (k >=1),所以实际上只要在计算DP[i][j]之前,把DP[i-1][j]存起来以备查询。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

伪代码

FOR i := 0 to n

  dp[i] := 0

END FOR

FOR i := 1 to n

  tmp := dp[0]

  FOR j := 1 to m

    IF a[i] = b[j]

      IF tmp = dp[j]

        dp[j] := tmp + 1

      ELSE

        tmp := dp[j]

      END IF

    ELSE

      tmp := dp[j]

      dp[j] := max{dp[j], dp[j-1]}

    END IF

  END FOR

END FOR

      

Longest Common Subsequence (LCS)的更多相关文章

  1. 动态规划求最长公共子序列(Longest Common Subsequence, LCS)

    1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...

  2. 最长公共字串算法, 文本比较算法, longest common subsequence(LCS) algorithm

    ''' merge two configure files, basic file is aFile insert the added content of bFile compare to aFil ...

  3. 动态规划 ---- 最长公共子序列(Longest Common Subsequence, LCS)

    分析: 完整代码: // 最长公共子序列 #include <stdio.h> #include <algorithm> using namespace std; ; char ...

  4. LintCode Longest Common Subsequence

    原题链接在这里:http://www.lintcode.com/en/problem/longest-common-subsequence/ 题目: Given two strings, find t ...

  5. Longest Common Subsequence

    Given two strings, find the longest common subsequence (LCS). Your code should return the length of  ...

  6. Longest Common Subsequence & Substring & prefix

    Given two strings, find the longest common subsequence (LCS). Your code should return the length of  ...

  7. Lintcode:Longest Common Subsequence 解题报告

    Longest Common Subsequence 原题链接:http://lintcode.com/zh-cn/problem/longest-common-subsequence/ Given ...

  8. [Algorithms] Longest Common Subsequence

    The Longest Common Subsequence (LCS) problem is as follows: Given two sequences s and t, find the le ...

  9. 【Lintcode】077.Longest Common Subsequence

    题目: Given two strings, find the longest common subsequence (LCS). Your code should return the length ...

随机推荐

  1. shell+curl监控网站页面(域名访问状态),并利用sedemail发送邮件

    应领导要求,对公司几个主要站点的域名访问情况进行监控.下面分享一个监控脚本,并利用sendemail进行邮件发送. 监控脚本如下:下面是写了一个多线程的网站状态检测脚本,直接从文件中读出站点地址,然后 ...

  2. docker下部署gitlab

    docker用来隔离应用还是很方便的,一来本身的操作较为简单,二来资源占用也比虚拟机要小得多,三来也较为安全,因为像数据库这样的应用不会再全局暴露端口,同时应用间的通信通过加密和端口转发,更加安全. ...

  3. kprobe原理解析(一)

    kprobe是linux内核的一个重要特性,是一个轻量级的内核调试工具,同时它又是其他一些更高级的内核调试工具(比如perf和systemtap)的“基础设施”,4.0版本的内核中,强大的eBPF特性 ...

  4. 05SpringMvc_映射器SimpleUrlHanderMapping

    这篇文章讲的还是映射器,映射器类有两种,前一篇文章讲的是BeanNameUrlHanderMapping映射器类.今天讲的是SimpleUrlHanderMapping映射器类. 这两个映射器类有什么 ...

  5. 通过jekyll建立静态网页

    部署一个网站需要三个步骤:(1) generating the site, (2) deploying it to the public Internet, and (3) assigning it ...

  6. AVR/Arduino定时/计数器、中断入门

    在Arduino中,可以使用AnalogWrite来使用硬件产生490Hz/980Hz的pwm波,并可根据参数来设定占空比.不了解这个的同学可以去AnalogWrite学习下,SecretsOfArd ...

  7. C#把某个数组的一部分复制到另一个数组中的两种方法:Buffer.BlockCopy和Array.Copy

    static void Main(string[] args) { , , , , , }; ;//目标数组大小 int int_size = sizeof(int);//用于获取值类型的字节大小. ...

  8. 使用ObjectAnimator设置动画

    ObjectAnimator是ValueAnimator的子类,他本身就已经包含了时间引擎和值计算,所以它拥有为对象的某个属性设置动画的功能.这使得为任何对象设置动画更加的容易.你不再需要实现 Val ...

  9. 手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单

    手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单   手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发Chrome扩 ...

  10. Android自动化压力测试图解教程——Monkey工具

    [置顶] Android自动化压力测试图解教程--Monkey工具 标签: 测试androidprofiling工具测试工具文档 2012-04-01 10:16 38185人阅读 评论(10) 收藏 ...