前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >LCS + Problem

LCS + Problem

作者头像
AngelNH
发布于 2020-04-16 07:41:05
发布于 2020-04-16 07:41:05
54000
代码可运行
举报
文章被收录于专栏:AngelNIAngelNI
运行总次数:0
代码可运行

longest comment subsequence

最长公共子序列(LCM)

参考博客

最长公共子序列,。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。

(1)字符子串:指的是字符串中连续的n个字符,如abcdefg中,ab,cde,fg等都属于它的字串。

(2)字符子序列:指的是字符串中不一定连续但先后顺序一致的n个字符,即可以去掉字符串中的部分字符,但不可改变其前后顺序。如abcdefg中,acdg,bdf属于它的子序列,而bac,dbfg则不是,因为它们与字符串的字符顺序不一致。

(3) 公共子序列:如果序列C既是序列A的子序列,同时也是序列B的子序列,则称它为序列A和序列B的公共子序列。如对序列 1,3,5,4,2,6,8,7和序列 1,4,8,6,7,5 来说,序列1,8,7是它们的一个公共子序列。

那么现在,我们再通俗的总结一下最长公共子序列(LCS):就是A和B的公共子序列中长度最长的(包含元素最多的)

我们用Ax表示序列A的连续前x项构成的子序列,即Ax= a1,a2,……ax, By= b1,b2,……by, 我们用LCS(x, y)表示它们的最长公共子序列长度,那原问题等价于求LCS(m,n)。为了方便我们用L(x, y)表示Ax和By的一个最长公共子序列。让我们来看看如何求LCS(x, y)。我们令x表示子序列考虑最后一项

(1) Ax = By

那么它们L(Ax, By)的最后一项一定是这个元素!

为什么呢?为了方便,我们令t = Ax = By, 我们用反证法:假设L(x,y)最后一项不是t,则要么L(x,y)为空序列(别忘了这个),要么L(x,y)的最后一项是Aa=Bb ≠ t, 且显然有a < x, b < y。无论是哪种情况我们都可以把t接到这个L(x,y)后面,从而得到一个更长的公共子序列。矛盾! 如果我们从序列Ax中删掉最后一项ax得到Ax-1,从序列By中也删掉最后一项by得到By-1,(多说一句角标为0时,认为子序列是空序列),则我们从L(x,y)也删掉最后一项t得到的序列是L(x – 1, y - 1)。为什么呢?和上面的道理相同,如果得到的序列不是L(x - 1, y - 1),则它一定比L(x - 1, y - 1)短(注意L(,)是个集合!),那么它后面接上元素t得到的子序列L(x,y)也比L(x - 1, y - 1)接上元素t得到的子序列短,这与L(x, y)是最长公共子序列矛盾。因此L(x, y) = L(x - 1, y - 1) 最后接上元素t,LCS(Ax, By) = LCS(x - 1, y - 1) + 1。

(2) Ax ≠ By

​ 仍然设t = L(Ax, By), 或者L(Ax, By)是空序列(这时t是未定义值不等于任何值)。则t ≠ Ax和t ≠ By至少有一个成立,因为t不能同时等于两个不同的值嘛!

(2.1)如果t ≠ Ax,则有L(x, y)= L(x - 1, y),因为根本没Ax的事嘛。

​ LCS(x,y) = LCS(x – 1, y)

(2.2)如果t ≠ By,l类似L(x, y)= L(x , y - 1)

​ LCS(x,y) = LCS(x, y – 1)

可是,我们事先并不知道t,由定义,我们取最大的一个,因此这种情况下,有LCS(x,y) = max(LCS(x – 1, y) , LCS(x, y – 1))。看看目前我们已经得到了什么结论:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
LCS(x,y) = 
(1) LCS(x - 1,y - 1) + 1      (Ax = By)
(2) max(LCS(x – 1, y) , LCS(x, y – 1))    (Ax ≠ By)

这时一个显然的递推式,光有递推可不行,初值是什么呢?显然,一个空序列和任何序列的最长公共子序列都是空序列!所以我们有:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
LCS(x,y) = 
(1) LCS(x - 1,y - 1) + 1 如果Ax = By
(2) max(LCS(x – 1, y) , LCS(x, y – 1)) 如果Ax ≠ By
(3) 0 如果x = 0或者y = 0

练习

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<string>
using namespace std;

int m,n;

char a[1010];
char b[1010];

int dp[1010][1010];
int main()
{
    cin>>n>>m;
    scanf("%s",a+1);
    scanf("%s",b+1);
    for(int i =1;i<=n;++i)
    {
        for(int j=1 ;j<=m;++j)
        {
            if(a[i]==b[j])
                dp[i][j] = dp[i-1][j-1] + 1;
            else if(dp[i-1][j]>dp[i][j-1])
                dp[i][j] = dp[i-1][j];
            else
            {
                dp[i][j] = dp[i][j-1];
            }
        }
    }
    cout<<dp[n][m]<<endl;
    system("pause");
    return 0;
}

HDU1159

板子题

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>

using namespace std;

char a[1010],b[1010];
int dp[1001][1001];
int main()
{
    while(~scanf("%s",a))
    {
        scanf("%s",b);
        memset(dp,0,sizeof(dp));
        int len1 = strlen(a);
        int len2 = strlen(b);
        for(int i =0;i<len1;++i)
        {
            for(int j =0;j<len2;++j)
            {
                if(a[i]==b[j])
                    dp[i+1][j+1] = dp[i][j] + 1;
                // else if(dp[i][j+1]>dp[i+1][j])
                //     dp[i+1][j+1] = dp[i][j+1];
                else
                {
                    dp[i+1][j+1] = max(dp[i+1][j],dp[i][j+1]);
                    //dp[i+1][j+1] = dp[i+1][j];
                }
            }
        }
        cout<<dp[len1][len2]<<endl;
        //cout<<len1<<endl;
        //cout<<len2<<endl;

    }
    return 0;
}

51Nod1006

求的是最长公共子串是什么。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>

using namespace std;

char a[1010],b[1010];
int dp[1010][1010];

int main()
{
    while(~scanf("%s",a+1))
    {
        scanf("%s",b+1);
        int len1 = strlen(a+1);
        int len2 = strlen(b+1);
        string s;
        for(int i =1;i<=len1;++i)
        {
            for(int j =1;j<=len2;++j)
            {
                if(a[i]==b[j])
                    dp[i][j] = dp[i-1][j-1] +1;
                else
                {
                    dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
                }
            }
        }
        int i = len1,j= len2;
        while(i>=1&&j>=1)
        {
            if(a[i] == b[j])
            {
                s+=a[i];
                i--;j--;
            }
            else if(dp[i-1][j]>dp[i][j-1])
                i--;
            else 
            {
                j--;
            }
            
        }
        reverse(s.begin(),s.end());
        cout<<s<<endl;
        s.clear();
      
        // cout<<len1<<endl;

    }
    return 0;
}

HDU1503

将两个字符串结合起来,他们的公共子串只输出一次

在LCS的基础之上加上路径记录,生成dp数组的时候做上标记,之后按顺序输出结果字符串。注意还要考虑一下没有公共子序列的情况。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<iostream>
#include<algorithm>
#include<cstring >
#include<string>

using namespace std;

int dp[110][110];
char a[110],b[110];

int main()
{
    while(~scanf("%s",a+1))
    {
        scanf("%s",b+1);
        int len1 = strlen(a+1);
        int len2 = strlen(b+1);
        memset(dp,0,sizeof(dp));

        for(int i =1;i<=len1;++i)
        {
            for(int j=1;j<=len2;++j)
            {
                if(a[i]==b[j])
                {
                    dp[i][j] = dp[i-1][j-1] +1;
                }
                else if(dp[i-1][j]>dp[i][j-1])
                {
                    dp[i][j] = dp[i-1][j];
                }
                else
                {
                    dp[i][j] = dp[i][j-1];
                }
                
            }
        }
        //cout<<dp[len1][len2]<<endl;
        string s;
        int i =len1,j=len2;
        while(i>=1&&j>=1)
        {
            if(a[i] == b[j])
            {
                s+=a[i];
                i--,j--;
            }
            else if(dp[i-1][j]>dp[i][j-1])
            {
                s+=a[i];
                i--;
            }
            else
            {
                s+=b[j];
                j--;
            }
        }
        while(i!=0)
        {
            s+=a[i];
            i--;
        }
        while(j!=0)
        {
            s+=b[j];
            j--;
        }
        reverse(s.begin(),s.end());
        cout<<s<<endl;

    }
    system("pause");
    return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-02-14|,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
线性DP总结(LIS,LCS,LCIS,最长子段和)
做了一段时间的线性dp的题目是时候做一个总结 线性动态规划无非就是在一个数组上搞嘛, 首先看一个最简单的问题: 一,最长字段和 下面为状态转移方程 for(int i=2;i<=n;i++) { if(dp[i-1]>=0) dp[i]=dp[i-1]+a[i]; else dp[i]=a[i]; } 例题
ShenduCC
2018/04/26
1.6K0
动态规划--Kin
动态规划: 1.最大子序列和 2.LIS最长递增子序列 3.LCS最长公共子序列 4.矩阵连乘 5.数字金字塔 1.最大子序列和 #include<iostream> using namespace std; int maxsub(int a[],int n) { int sum=0,b=0; for(int i=0;i<=n;i++) { if(b>0) b+=a[i]; else b=a[i]; if(b>sum) sum=b; } return s
Kindear
2018/05/09
5440
LCS/最长公共子序列/最长公共子串 实现 Python/Java
http://blog.csdn.net/u012102306/article/details/53184446 http://blog.csdn.net/hrn1216/article/details/51534607
蛮三刀酱
2019/03/26
1K0
LCS/最长公共子序列/最长公共子串 实现 Python/Java
SDUT 2019 级程序设计基础(B)II 实验6–动态规划
在下面的数字三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大。路径上的每一步都只能往左下或 右下走。只需要求出这个最大和即可,不必给出具体路径。 三角形的行数n大于1小于等于100,数字为 0 – 99 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
Here_SDUT
2022/06/29
3270
SDUT 2019 级程序设计基础(B)II 实验6–动态规划
最长公共子序列与最长公共子串(DP)
比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与母串保持一致,我们将其称为公共子序列。最长公共子序列(Longest Common Subsequence,LCS),顾名思义,是指在所有的子序列中最长的那一个。子串是要求更严格的一种子序列,要求在母串中连续地出现。在上述例子的中,最长公共子序列为blog(cnblogs,belong),最长公共子串为lo(cnblogs, belong)。
蛮三刀酱
2019/09/11
6260
POJ-1458 Common Subsequence(线性动规,最长公共子序列问题)
Common Subsequence Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 44464 Accepted: 18186 Description A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = < x1
ShenduCC
2018/04/25
9130
最长公共子序列与最长公共子串
0. 引言 最近鄙人面试百度,出了这道求解公子序列长度的算法题。故此总结一下,这是一个很典型的题目,希望对大家将来的面试中能起到学习的作用。 1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与母串保持一致,我们将其称为公共子序列。最长公共子序列(Longest Common Subsequence,LCS),顾名思义,是指在所有的子序列中最长的那一个。子串
机器学习算法工程师
2018/03/06
1.2K0
最长公共子序列与最长公共子串
动态规划-LCS、LIS
LCS(Longest Common Subsequence)最长公共子序列。给定两个序列a和b,当另一序列c即是a的子序列又是b的子序列时,称c时a和b的公共子序列,最长公共子序列时所有子序列中长度最长的。 注意子序列是在原序列中删去若干元素后得到的序列,注意子序列≠子串,子串在原序列中是连续的。
唔仄lo咚锵
2020/09/15
5630
文心一言 VS 讯飞星火 VS chatgpt (207)-- 算法导论15.4 4题
在只使用 2 * min(m, n) 个表项和 O(1) 额外空间来计算 LCS(Longest Common Subsequence)的长度时,我们可以采用滚动数组(Rolling Array)的技巧。这种方法的核心思想是在填充 DP 表时只保留前一行的数据,因为当前行的数据只依赖于前一行的数据。这样我们就可以避免存储整个二维数组,而只存储一行数组即可。
福大大架构师每日一题
2024/03/06
1660
文心一言 VS 讯飞星火 VS chatgpt (207)-- 算法导论15.4 4题
每日一刷《剑指offer》字符串篇之正则表达式匹配
在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab_ac_a"匹配,但是与"aa.a"和"ab*a"均不匹配
终有救赎
2023/11/18
1340
每日一刷《剑指offer》字符串篇之正则表达式匹配
浅谈我对动态规划的一点理解---大家准备好小板凳,我要开始吹牛皮了~~~
前言 作为一个退役狗跟大家扯这些东西,感觉确实有点。。。但是,针对网上没有一篇文章能够很详细的把动态规划问题说明的很清楚,我决定还是拿出我的全部家当,来跟大家分享我对动态规划的理解,我会尽可能的把所遇到的动态规划的问题都涵盖进去,博主退役多年,可能有些地方会讲的不完善,还望大家多多贡献出自己的宝贵建议,共同进步~~~ 概念 首先我们得知道动态规划是什么东东,百度百科上是这么说的,动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数
Angel_Kitty
2018/04/08
4.6K0
浅谈我对动态规划的一点理解---大家准备好小板凳,我要开始吹牛皮了~~~
poj-------Common Subsequence(poj 1458)
Common Subsequence Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 34477 Accepted: 13631 Description A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = < x1, x2
Gxjun
2018/03/21
6450
C++ 动态规划经典案例解析之最长公共子序列(LCS)_窥探递归和动态规划的一致性
动态规划处理字符相关案例中,求最长公共子序列以及求最短编辑距离,算是经典中的经典案例。
一枚大果壳
2023/08/18
6780
C++ 动态规划经典案例解析之最长公共子序列(LCS)_窥探递归和动态规划的一致性
POJ 1458 Common Subsequence(最长公共子序列LCS)「建议收藏」
首先令dp[i][j]==x表示A串的前i个字符和B串的前j个字符的最长公共子序列长度为x.
全栈程序员站长
2022/07/10
3240
动态规划-各种子序列问题集合
当i=1,则dp[1]=2;因为dp[i]会和之前每一个元素j代替进行比对,当a[i]<a[j],并且dp[j]+1>dp[i].则dp[i]=dp[j]+1
十四君
2019/11/24
4630
LCS、LIS、LICS算法
给定两个序列 ,设 为 的长度,其中 分别表示 从首元素到第 i 个元素的一段、 从首元素到第 个元素的一段, 分别表示 中第 i个元素、 中第 个元素,序列 和 的长度分别为 和 。则 的状态转移方程为:
hotarugali
2022/03/01
8500
DP专题 3 | LCS最长公共子序列 - POJ 1458
A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = < x1, x2, ..., xm > another sequence Z = < z1, z2, ..., zk > is a subsequence of X if there exists a strictly increasing sequence < i1, i2, ..., ik > of indices of X such that for all j = 1,2,...,k, xij = zj. For example, Z = < a, b, f, c > is a subsequence of X = < a, b, c, f, b, c > with index sequence < 1, 2, 4, 6 >. Given two sequences X and Y the problem is to find the length of the maximum-length common subsequence of X and Y.
ACM算法日常
2019/06/17
4680
DP专题 3 | LCS最长公共子序列 - POJ 1458
文心一言 VS 讯飞星火 VS chatgpt (205)-- 算法导论15.4 1题
在Go语言中,求两个序列的最长公共子序列(Longest Common Subsequence, LCS)可以使用动态规划(Dynamic Programming, DP)的方法。下面是一个Go语言实现的示例代码,用于找到给定两个序列的LCS:
福大大架构师每日一题
2024/03/06
1890
文心一言 VS 讯飞星火 VS chatgpt (205)-- 算法导论15.4 1题
【面试高频题】难度 1.5/5,LCS 模板题
给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 。
宫水三叶的刷题日记
2022/10/05
3140
洛谷P1852 奇怪的字符串
题目描述 输入两个01串,输出它们的最长公共子序列的长度 输入输出格式 输入格式: 一行,两个01串 输出格式: 最长公共子序列的长度 输入输出样例 输入样例#1:  01010101010 00000011111 输出样例#1:  6 说明 01串长度≤10000 数据好水啊 一开始想了一个dp[i]表示以b中到达i位置最长的LCS,f[i]表示他的位置,然后转移就好,不过这样只能处理LCS是从1开始的情况 比如 01110 101100这个数据就过不去了, 然而。。 我得了90.。。。。。。。 后来加了
attack
2018/04/11
1.3K0
洛谷P1852 奇怪的字符串
相关推荐
线性DP总结(LIS,LCS,LCIS,最长子段和)
更多 >
LV.1
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档