版权声明:本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址

http://blog.csdn.net/lzuacm

C++版 - Lintcode 77-Longest Common Subsequence最长公共子序列(LCS) - 题解

在线提交(不支持C#):

https://www.lintcode.com/problem/longest-common-subsequence/

题目描述

一个字符串的一个子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。例如,”ACE” 是 “ABCDE” 的一个子序列,而 “AEC” 不是)。

给出两个字符串,找到最长公共子序列(LCS),返回LCS的长度。

说明

样例

给出“ABCD”“EDCA”,这个LCS是 “A” (或 D或C),返回1

给出 “ABCD”“EACB”,这个LCS是“AC”返回 2

注意

序列可以不连续。


  ● Difficulty: Medium
  • Total Accepted: 18202

  • Total Submitted: 45985

  • Accepted Rate: 39%

Tags:

Longest Common Subsequence

LintCode Copyright

Dynamic Programming(DP)

分析:

将算式的计算结果记录在内存中,需要时直接调用该结果,从而避免无用的重复计算,提高处理效率,这在程序和算法设计中是一种行之有效的手法。动态规划就是这类手法之一。

事实上动态规划是一种记忆化递归(memorized recursive),缓存部分重要数据。另外,动态规划法可以建立递归式,通过循环顺次求出最优解。

为方便说明,这里我们用Xi" role="presentation">XiXi代表{x1,x2,⋯,xi" role="presentation">x1,x2,⋯,xix1,x2,⋯,xi},用Yj" role="presentation">YjYj代表{y1,y2,⋯,yj" role="presentation">y1,y2,⋯,yjy1,y2,⋯,yj }。那么,求长度分别为m、n的两个序列XY的LCS,就相当于求Xm" role="presentation">XmXm与Yn" role="presentation">YnYn的LCS。我们将其分割为局部问题进行分析。

首先,求Xm" role="presentation">XmXm与Yn" role="presentation">YnYn的LCS时要考虑以下两种情况:

  • 当xm=yn" role="presentation">xm=ynxm=yn时,在Xm−1" role="presentation">Xm−1Xm−1与Yn−1" role="presentation">Yn−1Yn−1的LCS后面加上xm(=yn)" role="presentation">xm(=yn)xm(=yn)就是xm" role="presentation">xmxm与yn" role="presentation">ynyn的LCS。

    举个例子,X=(a,b,c,c,d,a),Y={a, b, c, b, a}时xm=yn" role="presentation">xm=ynxm=yn,所以在Xm−1" role="presentation">Xm−1Xm−1与Yn−1" role="presentation">Yn−1Yn−1的LCS({a, b,c})后面加上xm" role="presentation">xmxm {=a) 即为Xm" role="presentation">XmXm与Yn" role="presentation">YnYn的LCS。

  • 当xm≠yn" role="presentation">xm≠ynxm≠yn时,Xm−1" role="presentation">Xm−1Xm−1与Yn" role="presentation">YnYn的LCS和Xm" role="presentation">XmXm与Yn−1" role="presentation">Yn−1Yn−1的LCS中更长的一方就是Xm" role="presentation">XmXm与Yn" role="presentation">YnYn的LCS。

    举个例子,X={a,b,c,c,d}, Y={a,b,c,b,a}时,Xm−1" role="presentation">Xm−1Xm−1与Yn" role="presentation">YnYn的LCS为{a,b,c),Xm" role="presentation">XmXm与Yn" role="presentation">YnYn的LCS为{a,b,c,b},因此Xm" role="presentation">XmXm与Yn−1" role="presentation">Yn−1Yn−1的LCS就是Xm" role="presentation">XmXm与Yn" role="presentation">YnYn的LCS。

这个算法对Xi" role="presentation">XiXi与Yj" role="presentation">YjYj同样适用。于是可准备下述函数,用来求解LCS的局部问题。

c[m+1][n+1]: 该二维数组中,c[i][j] 代表Xi" role="presentation">XiXi与Yj" role="presentation">YjYj的LCS的长度

c[i][j] 的值可由下述递推公式(Recursive Formula)求得。

c[i][j]={0i=0 || j=0c[i−1][j−1]+1i,j>0 and xi=yjmax(c[i][j−1],c[i−1][j])i,j>0 and xi≠yj" role="presentation">c[i][j]=⎧⎩⎨0c[i−1][j−1]+1max(c[i][j−1],c[i−1][j])i=0 || j=0i,j>0 and xi=yji,j>0 and xi≠yjc[i][j]={0i=0 || j=0c[i−1][j−1]+1i,j>0 and xi=yjmax(c[i][j−1],c[i−1][j])i,j>0 and xi≠yj

基于上述变量和公式,可以用动态规划法求序列XY的LCS。

已AC代码如下:

class Solution {
public:
    int longestCommonSubsequence(string &A, string &B) {
        int m = A.size();
        int n = B.size();

        int **c = (int **)malloc((m+1) * sizeof(int *));
        for (int i = 0; i < m + 1; i++)
            c[i] = (int *)malloc((n+1) * sizeof(int));

        int max1 = 0;
        A = ' ' + A;
        B = ' ' + B;
        for (size_t i = 1; i <= m; i++)
            c[i][0] = 0;
        for (size_t j = 1; j <= n; j++)
            c[0][j] = 0;

        for (size_t i = 1; i <= m; i++)
        {
            for (size_t j = 0; j <= n; j++)
            {
                if (A[i] == B[j])
                {
                    c[i][j] = c[i - 1][j - 1] + 1;
                }
                else
                    c[i][j] = max(c[i][j - 1], c[i - 1][j]);
                max1 = max(max1, c[i][j]);
            }
        }
        return max1;
    }
};

Rank:

您的提交打败了 92.60% 的提交.

扩展阅读:

最长公共子序列问题 - Fogsail Chen - SegmentFault 思否

https://segmentfault.com/a/1190000008521545

C++版 - Lintcode 77-Longest Common Subsequence最长公共子序列(LCS) - 题解的更多相关文章

  1. lintcode 77.Longest Common Subsequence(最长公共子序列)、79. Longest Common Substring(最长公共子串)

    Longest Common Subsequence最长公共子序列: 每个dp位置表示的是第i.j个字母的最长公共子序列 class Solution { public: int findLength ...

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

    POJ1458 Common Subsequence(最长公共子序列LCS) http://poj.org/problem?id=1458 题意: 给你两个字符串, 要你求出两个字符串的最长公共子序列 ...

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

    最长公共子序列 英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已 ...

  4. LCS修改版(Longest Common Subsequence 最长公共子序列)

    题目描述 作为一名情报局特工,Nova君(2号)有着特殊的传达情报的技巧.为了避免被窃取情报,每次传达时,他都会发出两句旁人看来意义不明话,实际上暗号已经暗含其中.解密的方法很简单,分别从两句话里删掉 ...

  5. LCS(Longest Common Subsequence)最长公共子序列

    最长公共子序列(LCS)是一个在一个序列集合中(通常为两个序列)用来查找所有序列中最长子序列的问题.这与查找最长公共子串的问题不同的地方是:子序列不需要在原序列中占用连续的位置 .最长公共子序列问题是 ...

  6. POJ 1458 Common Subsequence 最长公共子序列 LCS

    LCS #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> ...

  7. HDU 1159 Common Subsequence 最长公共子序列

    HDU 1159 Common Subsequence 最长公共子序列 题意 给你两个字符串,求出这两个字符串的最长公共子序列,这里的子序列不一定是连续的,只要满足前后关系就可以. 解题思路 这个当然 ...

  8. hdu 1159 Common Subsequence(最长公共子序列 DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1159 Common Subsequence Time Limit: 2000/1000 MS (Jav ...

  9. Common Subsequence(最长公共子序列)

    A subsequence of a given sequence is the given sequence with some elements (possible none) left out. ...

随机推荐

  1. Linux学习之shell

    通配符 *:表示从它所在位置开始到某个符合条件的结束符之间的任何字符 ?:表示它所在位置上的任何可能的单个字符 []:表示[]中所包含字符的任何一个 特殊键 ctrl+c  #停止当前程序执行 ctr ...

  2. 实验5 Spark SQL 编程初级实践

    源文件内容如下(包含 id,name,age),将数据复制保存到 ubuntu 系统/usr/local/spark 下, 命名为 employee.txt,实现从 RDD 转换得到 DataFram ...

  3. 09-Python入门学习-函数基础与参数

    一.函数基础 1.定义函数的三种形式 1.1 无参函数 def foo(): print('from foo') foo() 1.2 有参函数 def bar(x,y): print(x,y) bar ...

  4. Cocos2d-js和Android交互

    说白了,就是JavaScript和Java之间的函数互相调用. 先看一下效果 有了这个交互,为了以后接sdk做准备. 要点: javascript调用java: jsb.reflection.call ...

  5. [转]XModem协议

    出处:XModem协议 XModem协议介绍:XModem是一种在串口通信中广泛使用的异步文件传输协议,分为XModem和1k-XModem协议两种,前者使用128字节的数据块,后者使用1024字节即 ...

  6. ORACLE启动报错ORA-03113: end-of-file on communication channel

    使用过程中发现oracle运行很慢(其实应该先关注空间问题),就准备关机重启一下,关不掉就强制关闭,然后启动就报错了. 1.SQL> startup ORACLE instance starte ...

  7. S7 Connection 通讯

    参考两个链接: http://www.ad.siemens.com.cn/service/answer/solution.aspx?Q_ID=74626&cid=1029 https://su ...

  8. Linux SVN服务器的搭建配置及分支的创建与合并

    第一步:通过yum命令安装svnserve,命令如下: >yum -y install subversion 若需查看svn安装位置,可以用以下命令: >rpm -ql subversio ...

  9. 关于docker jenkins启动时失败的问题处理

    最近在做持续集成,然后使用docker 运行jenkins docker run -d  -p 8088:8080 -p 50000:50000 -v /home/docker/jenkins_hom ...

  10. Flutter 获取服务器数据

    文档 文档版本有些老 使用 dio 来获取数据 demo import 'dart:io'; import 'dart:convert'; import 'package:flutter/materi ...