最长公共上升子序列(LCIS)

这篇具有很好参考价值的文章主要介绍了最长公共上升子序列(LCIS)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、前言

二、最长公共上升子序列

1、问题描述

2、基本思路

(1)状态表示

(2)状态计算

三、题例

1、上链接

2、基本思路

3、代码

(1)python未优化版

(2)python优化版


一、前言

对于学计算机的同学来说,学习算法是一件非常重要的事情,废话不多讲,我们来讲讲“最长公共上升子序列问题”。

二、最长公共上升子序列

1、问题描述

给定两个长度为 n 的数组  a[n],b[n]
求两个数组的 最长公共上升子序列 长度

2、基本思路

首先,这个问题是两个经典 dp 模型的结合:

LIS  (最长上升子序列,Longest Increasing Subsequence)

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

LCIS (最长公共上升子序列,Longest Common Increasing Subsequence)

使用闫氏dp分析法进行简单的思路分析。

(1)状态表示

集合f[i][j] :考虑 a 中前 i 个数字,b 中前 j 个数字 ,且当前以 b[j] 结尾的子序列的方案;

f[i][j]的性质:方案中子序列长度最大值——max

(2)状态计算

下面大部分引用y总原话:

首先依据公共子序列中是否包含 a[i],将 f[i][j] 所代表的集合划分成两个不重不漏的子集:

(1)不包含a[i]的子集(即我不选 a[i],因为 a[i]!=b[j]),显然最大值是 f[i - 1][j];

(2)包含a[i]的子集(即我选 a[i],因为 a[i]==b[j] 了),则需要将这个子集继续划分,依据是子序列的倒数第二个元素在 b[] 中是哪个数:

  • 子序列只包含 b[j] 一个数,长度是1;
  • 子序列的倒数第二个数是b[1]的集合,最大长度是f[i - 1][1] + 1;
  • 子序列的倒数第二个数是b[2]的集合,最大长度是f[i - 1][2] + 1;
  • .......
  • 子序列的倒数第二个数是b[j - 1]的集合,最大长度是f[i - 1][j - 1] + 1;

最长公共上升子序列(LCIS)

最长公共上升子序列(LCIS)

然后就是比较取最大值了。

即状态转移方程为:

f[i][j] = f[i−1][j]            (a[i]≠b[j]) 
f[i][j] = max(f[i−1][j], f[i−1][t]+1)       (a[i]==b[j])  

三、题例

1、上链接

272. 最长公共上升子序列 - AcWing题库

2、基本思路

如上。

3、代码

(1)python未优化版

N=int(input())

a=[0]+list(map(int,input().split()))
b=[0]+list(map(int,input().split()))

dp=[[0 for i in range(N+2)] for j in range(N+2)]

for i in range(1,N+1):
    for j in range(1,N+1):
        dp[i][j]=dp[i-1][j]
        if a[i]==b[j]:       # 公共
            for k in range(1,j):
                if b[j]>b[k]:     #上升
                    dp[i][j]=max(dp[i][j],dp[i-1][k]+1)

print(max(dp[N]))

'''
时间复杂度:O(n^3)

毫无疑问会超时

这个代码主要是用来理解这个DP模型,因为接下来的优化,和DP无关,是代码的等价变形
'''

'''
/*另一个三重循环*/
for (int i = 1; i <= n; i ++ )
{
    for (int j = 1; j <= n; j ++ )
    {
        f[i][j] = f[i - 1][j];
        if (a[i] == b[j])
        {
            int maxv = 1;
            for (int k = 1; k < j; k ++ )
                if (a[i] > b[k])
                    maxv = max(maxv, f[i - 1][k] + 1);
            f[i][j] = max(f[i][j], maxv);
        }
    }
}
'''

(2)python优化版

N=int(input())

a=[0]+list(map(int,input().split()))
b=[0]+list(map(int,input().split()))

dp=[[0 for i in range(N+2)] for j in range(N+2)]

for i in range(1,N+1):
    maxv=1
    for j in range(1,N+1):
        dp[i][j]=dp[i-1][j]
        if a[i]==b[j]:
            dp[i][j]=max(dp[i][j],maxv)
        if b[j]<a[i]:
            maxv=max(maxv,dp[i-1][j]+1)  #为什么这样更新最大值其实我没有很懂
                                        #后面懂了,因为k是对j的枚举,对代码的等价变形,先看看上面朴素法三重循环有maxv版

print(max(dp[N]))


'''
然后我们发现每次循环求得的maxv是满足 a[i] > b[k] 的 f[i - 1][k] + 1 的前缀最大值。

因此可以直接将maxv提到第一层循环外面,减少重复计算,此时只剩下两重循环。

而每次用到的 状态 都是第 i - 1 个阶段的

因此我们可以用一个变量,存储上一个阶段的能够接在 a[i] 前面的最大的状态值

'''

以上,最长公共上升子序列

祝好~文章来源地址https://www.toymoban.com/news/detail-407112.html

到了这里,关于最长公共上升子序列(LCIS)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 动态规划——最长上升子序列模型

    状态表示 f [ i ] : { 集合:所有以第 i 个数结尾的上升子序列  属性:子序列长度的 M a x 状态表示f[i]: begin{cases} 集合:所有以第 i 个数结尾的上升子序列\\\\ 属性:子序列长度的rm Max end{cases} 状态表示 f [ i ] : { 集合:所有以第 i 个数结尾的上升子序列   属性:子序列长

    2024年04月17日
    浏览(46)
  • C++---最长上升子序列模型---最大上升子序列和(每日一道算法2023.3.3)

    注意事项: 本题为\\\"线性dp—最长上升子序列的长度\\\"的扩展题,所以dp思路这里就不再赘述。 题目: 比如,对于序列(1,7,3,5,9,4,8),有它的一些上升子序列,如(1,7),(3,4,8)等。 这些子序列中和最大为18,为子序列(1,3,5,9)的和。 你的任务,就是对于给定的序列,求出最大上升子序

    2024年02月03日
    浏览(39)
  • 动态规划__最长上升子序列

    目录 一.最长上升子序列 最长上升子序列模板 O(n ^ 2) 最长上升子序列二分优化 O(nlongn) 1017. 怪盗基德的滑翔翼 1014. 登山 1012. 友好城市 1016. 最大上升子序列和 1010. 拦截导弹 187. 导弹防御系统 二.最长公共上升子序列 最长公共子序列 最长公共上升子序列 给定一个长度为 N 的数

    2024年02月04日
    浏览(41)
  • C++动态规划之最长上升子序列

    一个序列A={a1,a2,...an}中任意删除若干项,剩余的序列叫做A的一个子序列。例如序列A={1,3,5,4,2},删除其中的第3项和第5项,得到序列B={1,3,4},删除其中的第3项和第4项,得到序列C={1,3,2},此时序列B和C是序列A的子序列。 如果序列中的元素是从小到大排列的,则该序列为上升

    2023年04月14日
    浏览(46)
  • 动态规划—— 最长上升子序列模型 解题记录

    一些想法:         现在是2024-3-15 06:01:22 哈哈卷死我可爱的舍友们~ 这两天又想起来开学的时候立下的刷完kuangbin专题的flag(快进到干不完) 总是先把Acwing的提高课看完吧 每天这样干一点总能干完的hhhhh,这会在喝npy买的奶茶,超多椰果真的好喝爱了爱了。 解题报告:

    2024年04月13日
    浏览(43)
  • 【C++】洛谷B3637 最长上升子序列

    这是一个简单的动规板子题。 给出一个由 n ( n ≤ 5000 ) n(nle 5000) n ( n ≤ 5000 ) 个不超过 1 0 6 10^6 1 0 6 的正整数组成的序列。请输出这个序列的 最长上升子序列 的长度。 最长上升子序列是指,从原序列中 按顺序 取出一些数字排在一起,这些数字是 逐渐增大 的。 第一行,一

    2024年02月19日
    浏览(33)
  • AcWing 1.2.1 最长上升子序列模型 + 动态规划 + 图解(详细)

    (1)acwing 4557. 最长上升子序列  4557. 最长上升子序列 - AcWing题库 给定一个长度为 N 的整数序列  a1,a2,…,aN 。请你计算该序列的 最长上升子序列的长度 。上升子序列是指数值 严格单调递增的子序列 输入格式 第一行包含整数 N 第二行包含 N个整数 a1,a2,…,aN 输出格式 一行

    2024年02月06日
    浏览(40)
  • 动态规划系列 | 最长上升子序列模型(下)| 拦截导弹一网打尽!

    题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。 但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。 某天,雷达捕捉到敌国的导弹来袭。 由于该系统还在试用阶段,所以只有一套

    2024年02月03日
    浏览(50)
  • 字符串---第一部分 序列、字串;上升,公共

    第一部分 最长上升子序列,最长上升子串,最长公共子序列,最长公共子串--dp 第二部分 KMP,trie,双指针 第三部分 待定 动态规划:审题,状态确定,状态转移,边界条件 线性DP 最长上升子序列 403 线性DP 最长上升子序列【动态规划】_哔哩哔哩_bilibili 给定一个无序整数数组

    2024年02月07日
    浏览(50)
  • 最长公共子序列和最长公共子串

    最长公共子序列 题目描述 给出1,2,…, n 的两个排列P 1 和 P 2 ,求它们的最长公共子序列。 输入格式 第一行是一个数 n 。 接下来两行,每行为 n 个数,为自然数1,2,…, n 的一个排列。 输出格式 一个数,即最长公共子序列的长度。 题目分析 第一阶段定义dp数组 (1)考虑规模

    2024年02月19日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包