[算法练习]最长公共子序列

题目说明:

找两个字符串的最长公共子序列,这个子序列不要求在原字符串中是连续的,但要求顺序是一致的,比如"abcd"和"aebfc"的最长公共子串是"abc"。

程序代码:

#include <gtest/gtest.h>
#include <vector>
using namespace std;

enum DirectionType
{
    TypeUp,
    TypeLeftUp,
    TypeLeft
};

int TMaxVal(int A, int B, int C, DirectionType& index)
{
    int nVal = A;
    index = TypeUp;

    if (B > nVal)
    {
        nVal = B;
        index = TypeLeftUp;
    }

    if (C > nVal)
    {
        nVal = C;
        index = TypeLeft;
    }

    return nVal;
}

// 按照上、左上、左的比较顺序
string GetLCS(const string& strA, const string& strB)
{
    int nLengthA = strA.length();
    int nLengthB = strB.length();

    if (!nLengthA || !nLengthB)
    {
        return "";
    }

    struct RecordInfo
    {
        char Direction;
        char Count;
    };

    RecordInfo* arrRecordInfo = new RecordInfo[(nLengthA + 1) * (nLengthB+1)];
    memset(arrRecordInfo, 0, (nLengthA + 1) * (nLengthB + 1) * sizeof(RecordInfo));

    for (int i = 1; i <= nLengthA; ++i)
    {
        for (int j = 1; j <= nLengthB; ++j)
        {
            int nNewVal = 0;
            DirectionType nDirect;
            if (strA[i-1] == strB[j-1])
            {
                nNewVal = TMaxVal(
                    arrRecordInfo[(i-1)*(nLengthB+1) + j].Count,
                    arrRecordInfo[(i-1)*(nLengthB+1) + j-1].Count + 1,
                    arrRecordInfo[i*(nLengthB+1) + j-1].Count,
                    nDirect);
            }
            else
            {
                nNewVal = TMaxVal(
                    arrRecordInfo[(i-1)*(nLengthB+1) + j].Count,
                    arrRecordInfo[(i-1)*(nLengthB+1) + j-1].Count,
                    arrRecordInfo[i*(nLengthB+1) + j-1].Count,
                    nDirect);
            }

            arrRecordInfo[i*(nLengthB+1) + j].Count = nNewVal;
            arrRecordInfo[i*(nLengthB+1) + j].Direction = nDirect;
        }
    }

    string strValue;
    int i = nLengthA;
    int j = nLengthB;
    while ((i > 0) && (j > 0))
    {
        int nDirect = arrRecordInfo[i*(nLengthB+1) + j].Direction;
        if (TypeLeftUp == nDirect)
        {
            if (strA[i-1] == strB[j-1])
            {
                strValue += strA[i-1];
            }

            --i;
            --j;
        }
        else if(TypeUp == nDirect)
        {
            --i;
        }
        else if(TypeLeft == nDirect)
        {
            --j;
        }
    }

    reverse(strValue.begin(),strValue.end());

    return strValue;
}

TEST(Algo, tLongestCommonSequence)
{
    //
    // "" ""
    // abcdefg   bdacafg
    // abcabcagc abcdcagb

    vector<string> result;
    ASSERT_EQ(GetLCS("",""),"");
    ASSERT_EQ(GetLCS("abcdefg","bdacafg"), "acfg");
}
时间: 2024-11-03 21:57:00

[算法练习]最长公共子序列的相关文章

算法学习 - 最长公共子序列(LCS)C++实现

最长公共子序列 最长公共子序列的问题很简单,就是在两个字符串中找到最长的子序列,这里明确两个含义: 子串:表示连续的一串字符 . 子序列:表示不连续的一串字符. 所以这里要查找的是不连续的最长子序列, 动态规划 这里为什么要使用动态规划可以说一下,简单来说动态规划是为了降低时间复杂度的一种算法,申请一个额外空间,来保存每一个步骤的结果,最后从这些结果中找到最优的解. 这里有个问题就是:一般来说,当前的最优解,只与当前时刻和上一时刻有关系,和其他时刻没有关系,这样才能让动态规划发生作用,降低复杂度

ACM/ICPC 之 最长公共子序列计数及其回溯算法(51Nod-1006(最长公共子序列))

这道题被51Nod定为基础题(这要求有点高啊),我感觉应该可以算作一级或者二级题目,主要原因不是动态规划的状态转移方程的问题,而是需要理解最后的回溯算法. 题目大意:找到两个字符串中最长的子序列,子序列的要求满足其中字符的顺序和字母在两个序列中都必须相同,任意输出一个符合题意的子序列 首先是最基本的最长公共子序列的状态转移问题: 这里的maxLen[i][j]数组的意思就是保存s1的前 i 个字符和s2的前 j 个字符匹配的状态. 举个例子:maxLen[3][6]即表明在s1的前3个字符和s2

【算法】最长公共子序列(nlogn)

转载注明出处:http://blog.csdn.net/wdq347/article/details/9001005 最长公共子序列(LCS)最常见的算法是时间复杂度为O(n^2)的动态规划(DP)算法,但在James W. Hunt和Thomas G. Szymansky 的论文"A Fast Algorithm for Computing Longest Common Subsequence"中,给出了O(nlogn)下限的一种算法. 定理:设序列A长度为n,{A(i)},序列B长

动态规划算法解最长公共子序列LCS问题

第一部分.什么是动态规划算法 ok,咱们先来了解下什么是动态规划算法. 动态规划一般也只能应用于有最优子结构的问题.最优子结构的意思是局部最优解能决定全局最优解(对有些问题这个要求并不能完全满足,故有时需要引入一定的近似).简单地说,问题能够分解成子问题来解决. 动态规划算法分以下4个步骤: 描述最优解的结构 递归定义最优解的值 按自底向上的方式计算最优解的值   //此3步构成动态规划解的基础. 由计算出的结果构造一个最优解.   //此步如果只要求计算最优解的值时,可省略. 好,接下来,咱们

字符串算法之最长公共子序列

最长公共子序列,即 longest common subsequence,LCS.一个字符串删掉任意字符后所形成的字符串,不要求连续,注意和最长公共子串的区别. LCS的应用:论文查重,图形相似度比较,基因序列比较等. 暴力求解: 分别求出X.Y串的子序列,而后进行搜索比较,容易得到该算法复杂度为O(2^m · 2^n ),显然不可取 动态规划: 设有两个字符串X[1....m],Y[1....n],求其最长公共子串 假设Xi Yi为两个字符串从1开始数的第i个字符,若xm=yn,则xm必在最长

算法 动态规划 ------最长公共子序列

这篇博客是我 听完这位老师讲完课的 记录.https://www.youtube.com/watch?v=mgDUoITB24I&t=645s    还有我个人的理解,如果有错误或者有争议的地方,欢迎留言.谢谢大家~ 子序列  就是说 从原有列表中按照出现先后顺序从中选择部分 元素 组成的新的列表. 最长公共子序列的含义:  选择两个列表中公共的子序列的最大长度,这个子序列即为最长公共子序列. 用蛮力的方法求解,对于长度为 M的 列表,它所有的子序列的个数有  2^m  ,每个元素有两种情况,被

动态规划算法之:最长公共子序列 & 最长公共子串(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"(当然我们现在一眼就可以看出来最长公共子串是

算法导论_动态规划_最长公共子序列

一.动态规划的概念 动态规划(Dynamic Programming)是通过组合子问题的解而解决整个问题的.分治是指将问题划分成一些独立的子问题,递归地求解各子问题,然后合并子问题的解而得到原始问题的解,与此不同,动态规划适用于子问题不是独立的情况,也就是各个子问题包含公共的子问题.在这种情况下,采用分治法会做许多不必要的工作,即重复地求解公共地子问题.动态规划算法对每个子问题只求解一次,将其结果保存在一张表中,从而避免每次遇到各个子问题时重新计算答案. 动态规划通常应用于最优化问题.此类问题可