272. 最长公共上升子序列

Posted yonezu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了272. 最长公共上升子序列相关的知识,希望对你有一定的参考价值。

技术图片

 

 解法一: f[i][j]表示数列A的前i个和数列B的前j个且以B[i]结尾的最长公共上升子序列

  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 <= t < j)

#include <iostream>
#include <cstring>
using namespace std;

const int N = 3030;
int n;
int a[N],b[N];
int f[N][N];

int main () {
    
    scanf("%d",&n);
    for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
    for(int i = 1; i <= n; i++) scanf("%d",&b[i]);
    int res = 0;
    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]) {
                
                for(int k = j - 1; k >= 1; k--) {
                    if(b[k] < b[j]) {
                        f[i][j] = max(f[i][j],f[i][k]+1);
                    }
                }
                
            }
            res = max(res,f[i][j]);
        }
    }
    printf("%d
",res);
    return 0;
    
}

解法二:优化时间复杂度,使用一个变量来维护遍历j之前的最大长度

#include <iostream>
#include <cstring>
using namespace std;

const int N = 3030;
int n;
int a[N],b[N];
int f[N][N];

int main () {
    
    scanf("%d",&n);
    for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
    for(int i = 1; i <= n; i++) scanf("%d",&b[i]);
    int res = 0;
    for(int i = 1; i <= n; i++) {
        int len = 0;
        for(int j = 1; j <= n; j++) {
            f[i][j] = f[i-1][j]; // 分为选i和不选i两种情况,这是不选i的情况
            
            if(a[i] == b[j]) f[i][j] = max(f[i][j],len + 1); // 更新f[i][j]
            if(a[i] > b[j]) len = max(len,f[i-1][j]); // 更新len
            res = max(res,f[i][j]);
        
        }
        
    }
    printf("%d
",res);
    return 0;
    
}

 

以上是关于272. 最长公共上升子序列的主要内容,如果未能解决你的问题,请参考以下文章

272. 最长公共上升子序列

最长上升子序列模型

刷题之最长公共/上升子序列问题

LIS LCS 最长上升子序列 最长公共子序列 ...

[codevs2185]最长公共上升子序列

最长公共上升子序列(codevs 2185)