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

前置知识

  1. LCS (最长公共子序列)

  1. LIS (最长上升子序列)

注意:

  刚开始看这个问题的时候,第一反应可能是先求出LCS再求出LCS的LIS,事实上这是有问题的,比如

1 2 3 9 8 7 6 5 4序列

9 8 7 6 5 4 1 2 3 序列

,筛选出的最长公共子序列应该是9 8 7 6 5 4,但是我们需要的最长公共上升子序列应该是 1 2 3

求解

设第一个串为a,第二个串为b

  1. 首先确定dp状态f[i, j],表示前a串前i个字符和b串前j个字符且以b[j]为结尾的LCIS

  1. 状态方程:

对于当处于(a[i], b[j]) 状态时 ,由于dp状态就决定了,b[j]是一定作为这个状态下LICS的结尾的,所以对于a[i],就有两种情况,将其纳入LCIS或者不纳入,首先先说不讲a[i]纳入LCIS的情况

(1)若是 a[i] != b[j] ,显然是一定不能将a[i]与b[j]进行配对的,那么问题就缩小成了前a的前i - 1个字符与b的前j个字符且以b[j]结尾的LCIS,即f[i - 1, j]也就是说 ,i之前的以b[j]结尾的序列自然没有改变,仍然是长度仍然是f[i−1][j]; 若是a[i] == b[i] 如果不想要a[i]与b[j]进行配对,是不是也会得到上面的结果,故当

不将a[i]与b[j]配对(或无法配对)时,f[i, j] = f[i - 1, j]

(2)当a[i] == b[j]且它们进行配对时,就要在a串前i - 1个字符和b的前j - 1个字符中找到一个最长的序列,设这个序列以t结尾且b[t] < b[j],是不是就等价于

f[i, j] = max(f[i - 1, t]) + 1 (t > 0 && t < j && b[t] < b[j])

这样就把这个问题可以转化为最优子结构的问题,且得到状态转移方程如下

讲上述思路转化为代码

上面代码的时间复杂度为O(n^3),是很不理想的,可以对其进行等价转化为O(n^2)的优化

观察第三层循环,可以发现每次循环求得的maxv是满足a[i] > b[k]的f[i - 1][k] + 1的前缀最大值。,而且是在a[i] == b[j]的时候成立,且可以发现,在每一次进行第二层循环时,a[i]是不变的,这也就可以推出,与a[i]进行配对的b[j]的值也是暂时不变的,那么把b[j]等价转化为a[i],并将maxv提至第一层循环内,在每一次比较a[i]和b[j]时,一起讲maxv处理出来,这样就可以将其优化为如下的O(n ^2)的代码

这样其实已经够了,但是追求优化的话,还可以进行空间的优化,不难发现,每一次都止利用了上一层的结果,那么可以采用滚动数组的方法进行空间优化

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值