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

题目描述

给定两个长度分别为n和m的序列A和B,求两个序列的最长公共上升子序列长度。
例如:
1 5 3 6 3 2 7 3 6 2 和 9 6 2 3 1 5 3 3 6 1 的最长上升子序列的长度为3。

题目分析

这是一道LISLCS的综合题目。

【状态定义】 d p [ i ] [ j ] dp[i][j] dp[i][j]表示序列 A [ 1 : i ] A[1:i] A[1:i]和序列 B [ 1 : j ] B[1:j] B[1:j]构成的以 B [ j ] [ B[j][ B[j][为结尾的LCIS长度。
【状态转移】 为:

  • A [ i ] ≠ B [ j ] A[i] ≠ B[j] A[i]=B[j] d p [ i ] [ j ] = d p [ i − 1 ] [ j ] dp[i][j] = dp[i-1][j] dp[i][j]=dp[i1][j] (可以理解为将 A [ i ] A[i] A[i]扔掉)
  • A [ i ] = B [ j ] A[i] = B[j] A[i]=B[j] d p [ i ] [ j ] = m a x { d p [ i − 1 ] [ k ] } dp[i][j] = max\{ dp[i-1][k]\} dp[i][j]=max{dp[i1][k]} , k k k 满足: k ∈ [ 0 , j ) , B [ k ] < B [ j ] k∈[0,j) ,B[k]<B[j] k[0,j),B[k]<B[j]
    d p [ ] [ j ] dp[][j] dp[][j]的子问题不是 d p [ ] [ j − 1 ] dp[][j-1] dp[][j1],而是满足单调性的 d p [ ] [ k ] dp[][k] dp[][k]

【边界条件】 d p [ 0 ] [ j ] = d p [ i ] [ 0 ] = 0 dp[0][j] = dp[i][0] = 0 dp[0][j]=dp[i][0]=0
【目标状态】 m a x { d p [ n ] [ j ] } max\{dp[n][j]\} max{dp[n][j]}, j ∈ [ 1 , m ] j ∈[1,m] j[1,m]

代码
int cal(){
    a[0] = b[0] = -inf;
    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];
            else{
                for(int k = 0;k<j;k++){ //注意k=0开始
                    if(b[k]<b[j])
                        dp[i][j] = max(dp[i][j],dp[i-1][k]+1);
                }
            }
        }
    }
    int ans=-inf;
    for(int j=1;j<=m;j++) ans = max(ans,dp[n][j]);
    return ans;
}

【细节注意】
B B B串当中,找不到 B [ k ] B[k] B[k]满足 B [ k ] < B [ j ] B[k]<B[j] B[k]<B[j]时, B [ 0 ] B[0] B[0]充当满足条件的 B [ k ] B[k] B[k],那么对于 B B B串来说,以 B [ j ] B[j] B[j]为结尾的LIS长度为1,即 B [ j ] B[j] B[j]本身。因此:

  • A [ 0 ] A[0] A[0] B [ 0 ] B[0] B[0] 定义为-∞。
  • k k k 0 0 0开始枚举
优化

注意观察状态转移公式,当 A [ i ] = B [ j ] A[i] = B[j] A[i]=B[j]时,决策集合为$ dp[i-1][k] , , k 满 足 满足 k∈[0,j) ,B[k]<B[j]$ ,由于 A [ i ] = B [ j ] A[i] = B[j] A[i]=B[j],即为满足 k ∈ [ 0 , j ) , B [ k ] < A [ i ] k∈[0,j) ,B[k]<A[i] k[0,j),B[k]<A[i]。 在内层循环中, i i i 的值不变, j j j的值递增。即决策集合的改变只受 B [ j ] B[j] B[j]的影响,如果 B [ j ] < A [ i ] B[j]<A[i] B[j]<A[i],则 d p [ i − 1 ] [ j ] dp[i-1][j] dp[i1][j]进入决策集合,否则决策集合不变。
定义变量 v v v为每轮最初的决策集合结果值, j j j递增前,判断:

  • B [ j ] < A [ i ] B[j]<A[i] B[j]<A[i], v = m a x ( v , d p [ i − 1 ] [ j ] ) v = max(v, dp[i-1][j]) v=max(v,dp[i1][j])
  • B [ j ] ≥ A [ i ] B[j] ≥ A[i] B[j]A[i], v v v不变
代码
int cal(){
    a[0] = b[0] = -inf;
    for(int i=1;i<=n;i++){
        int v=0;
        for(int j=1;j<=m;j++){
            if(a[i] != b[j]) dp[i][j] = dp[i-1][j];
            else dp[i][j] = v+1;
            if(b[j] < a[i]) v = max(v,dp[i-1][j]);
        }
    }
    int ans=-inf;
    for(int j=1;j<=m;j++) ans = max(ans,dp[n][j]);
    return ans;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值