动态规划之最长公共上升子序列(LCIS)算法及优化&&Openjudge2000:最长公共子上升序列

本文详细解析了如何将LCS和LIS合并,通过动态规划解决最长上升公共子序列问题。介绍了从原始O(N*M^2)到优化后的O(N*M)算法,包括状态转移方程的推导和空间复杂度的降低。并提供了代码实例和优化策略,适用于算法竞赛和编程学习者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

动态规划之最长公共上升子序列(LCIS)算法及优化

  • 例题

题目传送门

描述
给定两个整数序列,写一个程序求它们的最长上升公共子序列。
当以下条件满足的时候,我们将长度为N的序列S1 , S2 , . . . , SN 称为长度为M的序列A1 , A2 , . . . , AM 的上升子序列:存在 1 <= i1 < i2 < . . . < iN <= M ,使得对所有 1 <= j <=N,均有Sj = Aij,且对于所有的1 <= j < N,均有Sj < Sj+1。
输入
每个序列用两行表示,第一行是长度M(1 <= M <= 500),第二行是该序列的M个整数Ai (-231 <= Ai < 231 )
输出
在第一行,输出两个序列的最长上升公共子序列的长度L。在第二行,输出该子序列。如果有不止一个符合条件的子序列,则输出任何一个即可。
样例输入/输出

5
1 4 2 5 -12
4
-12 1 2 4

2
1 4

  • 问题分析

:这道题就是把之前学过的LCS和LIS合到一起了,所以参考之前LCS的状态转移方程,不难得到此题的状态转移方程:
① a[i] != b[j], dp[i][j] = dp[i-1][j]
② a[i] == b[j], dp[i][j] = max(dp[i-1][k]+1) (1 <= k <= j-1 && b[j] > b[k])

这里a[i]==b[i]的情况和LCS基本相同,只不过加入了k来确保在1到j-1区间能转移的数小于b[j](和LIS的原理一样),这里如果不理解就是LIS理解不到位,可以参考其他LIS的博客。a[i]!=b[i]的情况和LCS不同,因为 dp[i][j] 是以 b[j] 为结尾的LCIS,如果 dp[i][j] > 0 那么就说明 a[1]…a[i] 中必然有一个整数 a[k] 等于 b[j] ,因为 a[k] != a[i] ,那么 a[i] 对 dp[i][j] 没有贡献,于是我们不考虑它照样能得出 dp[i][j] 的最优值。所以在 a[i] != b[j] 的情况下必然有 dp[i][j] == dp[i-1][j] ,所以这也解释了为什么LCIS中没有LCS里dp[i][j]=dp[i][j-1]的情况。

  • 代码实现及优化

根据状态转移方程及分析,不难写出最朴素的O(N * M^2)算法
代码

int LCIS(int *a,int n,int *b,int m) 
{
   
    int ans=0;
    int dp[505][505]={
   0};
    int tmp=0;
    for (int i=0;i<n;i++) 
	{
   
        for(int j=0;j<m;j++) 
		{
   
            dp[i+1][j+1]=dp[i][j+1];
            if(a[i]==b[j]) 
			{
   
                tmp=0;
                for(int k=0;k<j;k++) 
				{
   
                    if(b[j]>b[k]&&tmp<=dp[i][k+1]) tmp=dp[i][k+1];
                }
                dp[i+1][j+1]=tmp+1;
            }
            ans=ans>dp[i+1][j+1]?ans:dp[i+1
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值