动态规划-最长公共上升子序列-n^2解法
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]\)进行分类讨论。
\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解法的更多相关文章
- 动态规划——最长公共上升子序列LCIS
问题 给定两个序列A和B,序列的子序列是指按照索引逐渐增加的顺序,从原序列中取出若干个数形成的一个子集,若子序列的数值大小是逐渐递增的则为上升子序列,若A和B取出的两个子序列A1和B1是相同的,则A1 ...
- [ACM_动态规划] UVA 12511 Virus [最长公共递增子序列 LCIS 动态规划]
Virus We have a log file, which is a sequence of recorded events. Naturally, the timestamps are s ...
- codevs 2185 最长公共上升子序列
题目链接: codevs 2185 最长公共上升子序列codevs 1408 最长公共子序列 题目描述 Description熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目.小沐沐先让奶牛研究了最长上升 ...
- HDOJ 1423 Greatest Common Increasing Subsequence 【DP】【最长公共上升子序列】
HDOJ 1423 Greatest Common Increasing Subsequence [DP][最长公共上升子序列] Time Limit: 2000/1000 MS (Java/Othe ...
- HDU 4512 最长公共上升子序列
各种序列复习: (1)最长上升子序列. 1.这个问题用动态规划就很好解决了,设dp[i]是以第i个数字结尾的上升子序列的最长长度.那么方程可以是dp[i]=max(dp[j]+1).(j<i). ...
- LCIS 最长公共上升子序列问题DP算法及优化
一. 知识简介 学习 LCIS 的预备知识: 动态规划基本思想, LCS, LIS 经典问题:给出有 n 个元素的数组 a[] , m 个元素的数组 b[] ,求出它们的最长上升公共子序列的长度. 例 ...
- hdu 1423 最长公共递增子序列 LCIS
最长公共上升子序列(LCIS)的O(n^2)算法 预备知识:动态规划的基本思想,LCS,LIS. 问题:字符串a,字符串b,求a和b的LCIS(最长公共上升子序列). 首先我们可以看到,这个问题具有相 ...
- 最长公共上升子序列(codevs 2185)
题目描述 Description 熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目.小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们要研究最长公共上升子序列了. 小沐沐说,对 ...
- 最长公共上升子序列(LCIS)
最长公共上升子序列慕名而知是两个字符串a,b的最长公共递增序列,不一定非得是连续的.刚开始看到的时候想的是先用求最长公共子序列,然后再从其中找到最长递增子序列,可是仔细想一想觉得这样有点不妥,然后从网 ...
随机推荐
- 3.使用nginx-ingress
作者 微信:tangy8080 电子邮箱:914661180@qq.com 更新时间:2019-06-25 13:54:15 星期二 欢迎您订阅和分享我的订阅号,订阅号内会不定期分享一些我自己学习过程 ...
- Redis之哨兵机制(sentinel)——配置详解及原理介绍
说到Redis不得不提哨兵模式,那么究竟哨兵是什么意思?为什么要使用哨兵呢? 接下来一一为您讲解: 1.为什么要用到哨兵 哨兵(Sentinel)主要是为了解决在主从(master-slave)复制架 ...
- set CSS style in js solutions All In One
set CSS style in js solutions All In One css in js set each style property separately See the Pen se ...
- css animation & animation-fill-mode
css animation & animation-fill-mode css animation effect https://developer.mozilla.org/en-US/doc ...
- node.js & Unbuntu Linux & nvm & npm
node.js & Unbuntu Linux & nvm & npm https://websiteforstudents.com/install-the-latest-no ...
- docs search & algolia & docsearch
docs search & algolia & docsearch https://www.algolia.com/docsearch https://www.algolia.com/ ...
- js & sort array object
js & sort array object sort array object in js https://flaviocopes.com/how-to-sort-array-of-obje ...
- classnames & React & taro
classnames & React & taro classnames https://www.npmjs.com/package/classnames demo https://g ...
- true && number !== boolean
true && number !== boolean bug let result = ``; // section, name ? create text, compute cent ...
- js 上传图片,用户自定义截取图片大小
js 上传图片,用户自定义截取图片大小 js 组件