1. 题目描述

给定两个数列\(A, B\),如果他们都包含一段位置不一定连续的数,且数值是严格递增的,那么称这一段数是两个数列的公共上升子序列。求\(A\)和\(B\)的最长公共上升子序列。

输入格式

第一行包含一个整数\(N\),表示\(A\)和\(B\)的长度。

第二行包含\(N\)个整数,表示数列\(A\)。

第三行包含\(N\)个整数,表示数列\(B\)。

输出格式

输出一个整数,表示最长公共上升子序列的长度。

数据范围

\(1 ≤ N≤ 3000\),序列中的数字均不超过\(2^{31} - 1\).

输入样例

4
2 2 1 3
2 1 2 3

输出样例

2

2. 朴素解法\(O(n^3)\)

朴素解法将最长公共子序列和最长上升子序列模型相结合。

用\(f[i][j]\)表示第一个序列的前\(i\)个数,和第二个序列的前\(j\)个数,且最后一个数为\(b[j]\)的最长公共上升子序列的长度。

则可以根据\(a[i]\)是否等于\(b[j]\)进行分类讨论。

\[f[i][j]=\left\{
\begin{array}{rcl}
f[i - 1][j] & & {a[i] != a[j]}\\
max_{k < j且b[k] < b[j]}(f[i][j], f[i- 1][k]) & & {a[i] == b[j] }\\

\end{array} \right.
\]

#include <iostream>
#include <algorithm> using namespace std;
const int N = 3010;
int a[N], b[N];
int n;
int f[N][N]; int main()
{
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i];
for(int i = 1; i <= n; i ++) cin >> b[i]; 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])
{
f[i][j] = max(f[i][j], 1);
for(int k = 1; k < j; k ++)
if(b[k] < b[j]) f[i][j] = max(f[i][j], f[i - 1][k] + 1);
}
}
}
int res = 0;
for(int i = 1;i <= n; i ++) res = max(res, f[n][i]);
cout << res << endl;
return 0;
}

3. 代码优化\(O(n^2)\)

上述朴素做法的时间复杂度为\(O(n^3)\)。那么我们如何优化呢?

  • 观察代码的最内层循环部分

     if(a[i] == b[j])
    {
    f[i][j] = max(f[i][j], 1);
    for(int k = 1; k < j; k ++)
    if(b[k] < b[j]) f[i][j] = max(f[i][j], f[i - 1][k] + 1);
    }

    由于执行最内层循环的时候a[i] == b[j]。所以最内层条件可以变为b[k] < a[i]

  • 再来考虑整个循环

    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])
    {
    f[i][j] = max(f[i][j], 1);
    for(int k = 1; k < j; k ++)
    if(b[k] < a[i]) f[i][j] = max(f[i][j], f[i - 1][k] + 1);
    }
    }
    }

    我们实际上就是在求:当第一个循环走到i,第二个循环走到j 且满足" a[i] > b[k]k < j "时f[i - 1][j]的最大值。

    也就是说当我们访问到第j层循环的时候,需要前j-1层的数据。因此,可以在j的循环中迭代求解。

    代码如下

    for(int i = 1; i <= n; i ++)
    {
    int maxv = 1;
    for(int j = 1; j <= n; j ++)
    {
    f[i][j] = f[i - 1][j];
    if(a[i] == b[j]) f[i][j] = max(f[i][j],maxv);
    if(b[j] < a[i]) maxv = max(maxv, f[i - 1][j] + 1); // maxv的更新一定要在f[i][j]的更新之后。
    }
    }

4. 总结

  • 本题是最长公共子序列模型和最长上升子序列模型的结合版, 我们可以根据最长上升子序列和最长公共子序列的状态表示方法得到启发,构建状态表示方法和状态转移方程。
  • 朴素解法的时间复杂度较高,但是我们可以根据代码进行优化,将时间复杂度由\(O(n^3)\)降到\(O(n^2)\)。

动态规划-最长公共上升子序列-n^2解法的更多相关文章

  1. 动态规划——最长公共上升子序列LCIS

    问题 给定两个序列A和B,序列的子序列是指按照索引逐渐增加的顺序,从原序列中取出若干个数形成的一个子集,若子序列的数值大小是逐渐递增的则为上升子序列,若A和B取出的两个子序列A1和B1是相同的,则A1 ...

  2. [ACM_动态规划] UVA 12511 Virus [最长公共递增子序列 LCIS 动态规划]

      Virus  We have a log file, which is a sequence of recorded events. Naturally, the timestamps are s ...

  3. codevs 2185 最长公共上升子序列

    题目链接: codevs 2185 最长公共上升子序列codevs 1408 最长公共子序列 题目描述 Description熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目.小沐沐先让奶牛研究了最长上升 ...

  4. HDOJ 1423 Greatest Common Increasing Subsequence 【DP】【最长公共上升子序列】

    HDOJ 1423 Greatest Common Increasing Subsequence [DP][最长公共上升子序列] Time Limit: 2000/1000 MS (Java/Othe ...

  5. HDU 4512 最长公共上升子序列

    各种序列复习: (1)最长上升子序列. 1.这个问题用动态规划就很好解决了,设dp[i]是以第i个数字结尾的上升子序列的最长长度.那么方程可以是dp[i]=max(dp[j]+1).(j<i). ...

  6. LCIS 最长公共上升子序列问题DP算法及优化

    一. 知识简介 学习 LCIS 的预备知识: 动态规划基本思想, LCS, LIS 经典问题:给出有 n 个元素的数组 a[] , m 个元素的数组 b[] ,求出它们的最长上升公共子序列的长度. 例 ...

  7. hdu 1423 最长公共递增子序列 LCIS

    最长公共上升子序列(LCIS)的O(n^2)算法 预备知识:动态规划的基本思想,LCS,LIS. 问题:字符串a,字符串b,求a和b的LCIS(最长公共上升子序列). 首先我们可以看到,这个问题具有相 ...

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

    题目描述 Description 熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目.小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们要研究最长公共上升子序列了. 小沐沐说,对 ...

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

    最长公共上升子序列慕名而知是两个字符串a,b的最长公共递增序列,不一定非得是连续的.刚开始看到的时候想的是先用求最长公共子序列,然后再从其中找到最长递增子序列,可是仔细想一想觉得这样有点不妥,然后从网 ...

随机推荐

  1. Kubernets二进制安装(16)之安装部署traefik(ingress)

    K8S的DNS实现了服务在集群"内"被自动发现,如何使得服务在Kuberneters集群"外"被使用和访问呢,有二种方法 1)使用NodePort型的Servi ...

  2. LVS+Keepalived深度理解,阐述你不知道的坑点

    1. LVS简介 1. 什么是LVS? LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统.本项目在1998年5月由章文嵩博士成立,是中国国内 ...

  3. Invalid prop: custom validator check failed for prop "***"

    使用element ui时,绑定参数参考官方参数说明,比如progress的status 值必须是在以下三个里面选择 "success/exception/text", 其它情况可 ...

  4. PostCSS All In One

    PostCSS All In One https://postcss.org/ https://www.webpackjs.com/loaders/postcss-loader/ https://gi ...

  5. setTimeout 实现原理, 机制

    setTimeout 实现原理, 机制 JS 执行机制说起 浏览器(或者说 JS 引擎)执行 JS 的机制是基于事件循环. 由于 JS 是单线程,所以同一时间只能执行一个任务,其他任务就得排队,后续任 ...

  6. AI & HR

    AI & HR 数字化人才画像 人力资本数字化管理 通过"AI+数据+专家"的手段,将"数字化人才画像"作为服务起点与信息入口,扩展提供全场景的数字化人 ...

  7. DevOps in Action

    DevOps in Action DevOps is a set of software development practices that combines software developmen ...

  8. CORS OPTIONS

    CORS OPTIONS A CORS preflight request is a CORS request that checks to see if the CORS protocol is u ...

  9. Dart 编写Api弃用警告

    例如body2在以后的版本将被bodyText1代替 @Deprecated( 'This is the term used in the 2014 version of material desig ...

  10. TYLER ADAMS BRADBERRY的私人投资分享

    TYLER ADAMS BRADBERRY是星盟全球投资公司(USA International Covenant 公司编号:20091457685)的创始人.投资委员会发起了15支项目基金,通过多方 ...