[算法系列之十九]最长公共子序列

题目

最长公共子序列

分析

有两个字符串S1和S2,求一个最长公共子串,即求字符串S3,它们同时是S1和S2的子串,且要求它们的长度最长,并确定这个长度。这个问题我们称之为最长公共子序列问题。
与求最长递增子序列一样,我们首先将原问题分割成一些子问题,我们用dp[i][j]表示S1中前i个字符和S2中前j个字符分别组成的两个前缀字符串的最长公共子串长度。显然的,当i,j较小时我们可以直接给出答案,如dp[0][j] 必等于0。那么,假设我们已经求的dp[i][j](0 <= i < x,0 <= j < y)的所有值,考虑如何在这些值继而推的dp[x][y],求的S1前x个字符组成的前缀子串和S2前y个字符组成的前缀子串的最长公共的子序列的长度。若S1[x] == S2[y],即S1中的第x个字符和S2中的第y个字符相同,同时由于他们都是各自前缀子串的最后一个字符,那么必存在一个最长的公共子串以S1[x]或S2[y]结尾。其他部分等价于S1中前x-1个字符和S2中前y-1个字符的最长公共子串。所以这个子串的长度比dp[x-1][y-1]增加1,即dp[x][y] = dp[x-1][y-1] + 1。相反的,若S1[x] != S2[y],此时其最长的公共子串长度为S1中前x-1个字符和S2中前y个字符的最长公共子串的长度与S1中前x个字符和S2中前y-1个字符的最长公共子串的长度的较大者,即在两种情况下得到的最长公共子串都不会因为其中一个字符串又增加了一个字符长度发生改变。综上所述,dp[x][y] = max{dp[x][y-1] , dp[x-1][y]}。
总结一下,最长公共子序列问题的递推条件:
假设有两个字符串S1和S2,其中S1长度为n,S2长度为m,用dp[i][j]表示S1前i个字符组成的前缀子串与S2前j个字符组成的前缀子串的最长公共子串长度,那么:

dp[0][j] = 0 (0 <= j <= m)
dp[i][0] = 0 (0 <= i <= n)
dp[i][j] = dp[i-1][j-1] + 1 (S1[i] == S2[j])
dp[i][j] = max{dp[i][j-1],dp[i-1][j]} (S1[i] != S2[j])

代码

/*---------------------------------------------
*   日期:2015-02-12
*   作者:SJF0115
*   题目: 19.最长公共子序列
*   来源:算法系列
*   博客:
-----------------------------------------------*/
#include <iostream>
#include <algorithm>
using namespace std;

class Solution {
public:
    int LCS(string a,string b){
        int sizea = a.size();
        int sizeb = b.size();
        if(sizea <= 0 || sizeb <= 0){
            return 0;
        }//if
        int dp[sizea+1][sizeb+1];
        // 初始化
        for(int i = 0;i < sizea;++i){
            for(int j = 0;j < sizeb;++j){
                if(i == 0 || j == 0){
                    dp[i][j] = 0;
                }//if
            }//for
        }//for
        // 递推
        for(int i = 1;i <= sizea;++i){
            for(int j = 1;j <= sizeb;++j){
                if(a[i] == b[j]){
                    dp[i][j] = dp[i-1][j-1] + 1;
                }//else
                else{
                    dp[i][j] = max(dp[i][j-1],dp[i-1][j]);
                }//else
            }//for
        }//for
        return dp[sizea][sizeb];
    }
};

int main() {
    Solution solution;
    string a("BDCABA");
    string b("ABCBDAB");
    cout<<solution.LCS(a,b)<<endl;
}
时间: 2024-08-27 08:43:27

[算法系列之十九]最长公共子序列的相关文章

算法系列(六)最长公共子序列(LCS)问题(连续子序列)的三种解法

最长公共子序列(LCS)问题有两种方式定义子序列,一种是子序列不要求不连续,一种是子序列 必须连续.上一章介绍了用两种算法解决子序列不要求连续的最终公共子序列问题,本章将介绍要求 子序列必须是连续的情况下如何用算法解决最长公共子序列问题. 仍以上一章的两个字符串 "abcdea"和"aebcda"为例,如果子序列不要求连续,其最长公共子序列为"abcda",如果子序列 要求是连续,则其最长公共子序列应为"bcd".在这种情况下

算法系列(五)最长公共子序列(LCS)问题(非连续子序列)的两种解法

最长公共子序列也称作最长公共子串,英文缩写是LCS(Longest Common Subsequence).其定义 是:一个序列S,如果分别是两个或多个已知序列的子序列,且是符合此条件的子序列中最长的,则称 S为已知序列的最长公共子序列. 关于子序列的定义通常有两种方式,一种是对子序列没有连 续的要求,其子序列的定义就是原序列中删除若干元素后得到的序列.另一种是对子序列有连续的要 求,其子序列的定义是原序列中连续出现的若干个元素组成的序列.求解子序列是非连续的最长公共 子序列问题是一个十分实用的

算法系列(十九) 用天文方法计算日月合朔(新月)

中国农历的朔望月是农历历法的基础,而朔望月又是严格以日月合朔发生的那一天作为月首,因此日 月合朔时间的计算是制定农历历法的关键.本文将介绍ELP-2000/82月球运行理论,以及如何用ELP- 2000/82月球运行理论计算日月合朔时间. 要计算日月合朔时间, 首先要对日月合朔这一天文现象进行数学定义.朔望月是在地球上观察到的月相周期,平均长度约等于 29.53059日,而恒星月(天文月)是月亮绕地球公转一周的时间,长度约27.32166日.月相周期长度比恒 星月长大约两天,这是因为在月球绕地球

Ruby实现的最长公共子序列算法

  这篇文章主要介绍了Ruby实现的最长公共子序列算法,本文直接给出实现代码,需要的朋友可以参考下 最长公共子序列,LCS,动态规划实现. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 #encoding: utf-8 #author:

算法知识之最长公共子序列问题(动态规划)

最近朋友让帮做个关于动态规划的最长公共子序列的问题,翻看以前的笔记并完成该题后,顺便写这样一篇文章,希望对大家有所帮助,同时也帮助自己回顾该知识点. 一.最长公共子序列的定义 子序列:若给定序列X={x1,x2,-,xm},则另一序列Z={z1,z2,-,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,-,ik}使得对于所有j=1,2,-,k有:zj=xij.公共子序列:给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列.最长公共子序列:给

[算法系列之十八]海量数据处理之BitMap

一:简介 所谓的BitMap就是用一个bit位来标记某个元素对应的Value, 而Key即是该元素.由于采用了bit为单位来存储数据,因此在存储空间方面,可以大大节省. 二:基本思想 我们用一个具体的例子来讲解,假设我们要对0-7内的5个元素(4,7,2,5,3)排序(这里假设这些元素没有重复).那么我们就可以采用BitMap的方法来达到排序的目的.要表示8个数,我们就只需要8个bit(1Bytes). (1)首先我们开辟1字节(8bit)的空间,将这些空间的所有bit位都置为0,如下图: (2

[算法系列之十四]字符串匹配之Morris-Pratt字符串搜索算法

前言 我们前面已经看到,蛮力字符串匹配算法和Rabin-Karp字符串匹配算法均非有效算法.不过,为了改进某种算法,首先需要详细理解其基本原理.我们已经知道,暴力字符串匹配的速度缓慢,并已尝试使用Rabin-Karp中的一个散列函数对其进行改进.问题是,Rabin-Karp的复杂度与强力字符串匹配相同,均为O(mn). 我们显然需要采用一种不同方法,但为了提出这种不同方法,先来看看暴力字符串匹配有什么不妥之处.事实上,再深入地研究一下它的基本原理,就能找到问题的答案了. 在暴力匹配算法中,需要检

经典算法题每日演练——第四题 最长公共子序列

一: 作用        最长公共子序列的问题常用于解决字符串的相似度,是一个非常实用的算法,作为码农,此算法是我们的必备基本功. 二:概念      举个例子,cnblogs这个字符串中子序列有多少个呢?很显然有27个,比如其中的cb,cgs等等都是其子序列,我们可以看出 子序列不见得一定是连续的,连续的那是子串.      我想大家已经了解了子序列的概念,那现在可以延伸到两个字符串了,那么大家能够看出:cnblogs和belong的公共子序列吗? 在你找出的公共子序列中,你能找出最长的公共子

支配点递推关系-求教下字符串最长公共子序列中支配点算法中几点问题。

问题描述 求教下字符串最长公共子序列中支配点算法中几点问题. 求支配点之间的递推关系 资料地址:http://www.doc88.com/p-140662466336.html