今天在看代码源文件求diff的原理的时候看到了LCS算法。这个算法应该不陌生,动规的经典算法。具体算法做啥了我就不说了,不知道的可以直接看《算法导论》动态规划那一章。既然看到了就想回忆下,当想到算法正确性的时候,发现这个算法的正确性证明并不好做。于是想了一段时间,里面有几个细节很trick,容易陷进去。想了几轮,现在把证明贴出来,有异议的可以留言一起交流。

先把一些符号和约定说明下:

假设有两个数组,A和B。A[i]为A的第i个元素,A(i)为由A的第一个元素到第i个元素所组成的前缀。m(i, j)为A(i)和B(j)的最长公共子序列长度。

由于算法本身的递推性质,其实只要证明,对于某个i和j:

m(i, j) = m(i-1, j-1) + 1 (当A[i] = B[j]时)

m(i, j) = max( m(i-1, j), m(i, j-1) ) (当A[i] != B[j]时)

第一个式子很好证明,即当A[i] = B[j]时。可以用反证,假设m(i, j) > m(i-1, j-1) + 1 (m(i, j)不可能小于m(i-1, j-1) + 1,原因很明显),那么可以推出m(i-1, j-1)不是最长的这一矛盾结果。

第二个有些trick。当A[i] != B[j]时,还是反证,假设m(i, j) > max( m(i-1, j), m(i, j-1) )。

由反证假设,可得m(i, j) > m(i-1, j)。这个可以推出A[i]一定在m(i, j)对应的LCS序列中(反证可得)。而由于A[i] != B[j],故B[j]一定不在m(i, j)对应的LCS序列中。所以可推出m(i, j) = m(i, j-1)。这就推出了与反正假设矛盾的结果。

得证。

LCS(最长公共子序列)动规算法正确性证明的更多相关文章

  1. DP_最长公共子序列/动规入门

    学自:https://open.163.com/movie/2010/12/L/4/M6UTT5U0I_M6V2U1HL4.html 最长公共子序列:(本文先谈如何求出最长公共子序列的长度,求出最长公 ...

  2. 算法设计 - LCS 最长公共子序列&&最长公共子串 &&LIS 最长递增子序列

    出处 http://segmentfault.com/blog/exploring/ 本章讲解:1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度:2. 与之类似但不同的 ...

  3. POJ 1458 Common Subsequence(LCS最长公共子序列)

    POJ 1458 Common Subsequence(LCS最长公共子序列)解题报告 题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?c ...

  4. 动态规划模板2|LCS最长公共子序列

    LCS最长公共子序列 模板代码: #include <iostream> #include <string.h> #include <string> using n ...

  5. LCS 最长公共子序列

    区别最长公共子串(连续) ''' LCS 最长公共子序列 ''' def LCS_len(x, y): m = len(x) n = len(y) dp = [[0] * (n + 1) for i ...

  6. LCS最长公共子序列(最优线性时间O(n))

    这篇日志主要为了记录这几天的学习成果. 最长公共子序列根据要不要求子序列连续分两种情况. 只考虑两个串的情况,假设两个串长度均为n. 一,子序列不要求连续. (1)动态规划(O(n*n)) (转自:h ...

  7. LCS最长公共子序列HDU1159

    最近一直在学习算法,基本上都是在学习动态规划以及字符串.当然,两者交集最经典之一则是LCS问题. 首先LCS的问题基本上就是在字符串a,b之间找到最长的公共子序列,比如 YAOLONGBLOG 和 Y ...

  8. LCS最长公共子序列

    问题:最长公共子序列不要求所求得的字符串在所给字符串中是连续的,如输入两个字符串ABCBDAB和BDCABA,字符串BCBA和BDAB都是他们的公共最长子序列 该问题属于动态规划问题 解答:设序列X= ...

  9. POJ 2250(LCS最长公共子序列)

    compromise Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u   Descri ...

随机推荐

  1. EXC_BAD_ACCESS(code...)坏内存访问 调试

    一般很多人遇到这个 都会崩溃 断点一般 找不到 原因 :  只能按照一步一步走readView的模式 : 一般是问题是  相互包含 比如  view2 在view1 上  但是在view2 又创建了一 ...

  2. 8.另类方法求1+2+...+n[AnotherMethodOfCalculateSumN]

    [题目] 求1+2+…+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字以及条件判断语句(A?B:C). [分析] 这道题没有多少实际意义,因为在软件开发中不 ...

  3. learn go recursive

    package main // 参考文章: // https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/06.6.md im ...

  4. Encode Adjacent Letters

    Encode a string by counting the consecutive letter. (i.e., "aaaabbxxxyyz" might become &qu ...

  5. input type = number 去除上下箭头,禁用滚轮事件(默认的自带滚轮加减数字)

    <style type="text/css"> /*盒子大小从边框开始计算*/ html * { box-sizing: border-box; } /*解决模态框抖动 ...

  6. asp.net如何判断服务器上的目录或文件是否存在

    asp.net判断服务器上的目录或文件是否存在!(实例) // ======================================================= [判断文件是否存在] u ...

  7. 洛谷 P1022 计算器的改良

    题解:字符串模拟 坑点: 1) 0/-1=-0. 这是因为(来自洛谷讨论区某大犇) double下存储的数字会有精度误差,比如0可能被存成0.000000000...01然而如果你乘上或者除以一个负数 ...

  8. Codeforces Round #249 (Div. 2)-D

    这场的c实在不想做,sad. D: 标记一下每个点8个方向不经过黑点最多能到达多少个黑点. 由题意可知.三角形都是等腰三角形,那么我们就枚举三角形的顶点. 对于每个定点.有8个方向能够放三角形. 然后 ...

  9. javascript正则表达式定义(语法)

    正则表达式的2种定义方法:一种是直接调用RegExp(),第二种是直接用字面量来定义,即var re = /正则规则/; 2种定义方法本质都是调用RegExp()方法 在调用同一段正则代码的时候,EC ...

  10. linux下使用tar命令详解

    解压语法:tar [主选项+辅选项] 文件或者目录 使用该命令时,主选项是必须要有的,它告诉tar要做什么事情,辅选项是辅助使用的,可以选用. 主选项: c 创建新的档案文件.如果用户想备份一个目录或 ...