yzoj1985 最长公共单调上升子序列 题解
题面给两个序列a,b长度分别为n,m求最长公共上升子序列,百度了一下求公共子序列的问题好像叫做LCS,而上升的叫做LCIS。都是dp的例题。
先来说说最长公共子序列,这是一道比较经典的dp题,我们可以很容易写出
1.状态F[i][j]表示a序列匹配到第i个b序列匹配到第j个的最长长度
2.状态转移方程
F[i][j] = max(F[i-1][j] , F[i][j-1]) (a[i] != b[j])
F[i][j] = F[i-1][j-1]+1(a[i] = b[j])
答案就在F[n][m]中
代码
#include<bits/stdc++.h>
using namespace std;
int n,m,f[5010][5010];
char a[5010],b[5010];
int main(){
scanf("%s",a+1);
scanf("%s",b+1);
n=strlen(a+1);
m=strlen(b+1);
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
f[i][j]=max(f[i-1][j],f[i][j-1]);
if(a[i]==b[j]) f[i][j]=f[i-1][j-1]+1;
}
}
printf("%d",f[n][m]);
return 0;
}
然后我们再来考虑最长公共上升子序列
1.定义状态:F[x][y]表示a串匹配长度x,b串匹配长度y,且以b[j]结尾的序列长度。
2.状态转移方程:
F[i][j]=F[i][j] = F[i-1][j] (a[i] != b[j])
F[i][j] = max(F[i-1][k]+1) (1 <= k <= j-1 && b[j] > b[k])
对于第一个方程我们可以理解为当a[i]!=a[j]时我们用b序列去匹配a序列匹配失败了则a[i]这个数是对这个序列没有贡献的,即考虑不考虑都无所谓
对于第二个方程我们可以理解为当b序列中第j个数匹配了,我们可以选择前面所有的状态进行转移,但是保证 b[j] > b[k]
#include<bits/stdc++.h>
using namespace std;
int n,m,ans,a[3010],b[3010],f[3010][3010];
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
for(int i=1;i<=m;++i) scanf("%d",&b[i]);
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
f[i][j]=f[i-1][j];
if(a[i]==b[j]){
int maxn=0;
for(int k=1;k<=j-1;++k){
if(b[j]>b[k]) maxn=max(maxn,f[i-1][k]);
}
f[i][j]=maxn+1;
}
}
}
for(int i=1;i<=m;++i) ans=max(ans,f[n][i]);
printf("%d",ans);
return 0;
}
但是这样的做法在最坏情况下可能到达O(n^3),我们可以考虑优化,我们可以发现在第三重循环找最大值时是否可以进行一定优化?我们可以发现当有一个序列a[i]=b[j]时看第二个转移方程b[j] > b[k]也就是说a[i]>b[k],我们可以利用一个最大值maxn来存下每次的最大值,即当a[i]>b[j]时更新它,当a[i]=b[j]时f[i][j]=maxn+1;
#include<bits/stdc++.h>
using namespace std;
int n,m,ans,a[3010],b[3010],f[3010][3010];
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
for(int i=1;i<=m;++i) scanf("%d",&b[i]);
for(int i=1;i<=n;++i){
int maxn=0;
for(int j=1;j<=m;++j){
f[i][j]=f[i-1][j];
if(a[i]>b[j]) maxn=max(maxn,f[i-1][j]);
if(a[i]==b[j]) f[i][j]=maxn+1;
}
}
for(int i=1;i<=m;++i) ans=max(ans,f[n][i]);
printf("%d",ans);
return 0;
}
我们依然可以发现f[i][j]转移只用到了f[i][j-1]的数,我们可以再进行优化!利用滚动数组优化我们的空间。
#include<bits/stdc++.h>
using namespace std;
int n,m,ans,a[3010],b[3010],f[3010];
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
for(int i=1;i<=m;++i) scanf("%d",&b[i]);
for(int i=1;i<=n;++i){
int maxn=0;
for(int j=1;j<=m;++j){
if(a[i]>b[j]) maxn=max(maxn,f[j]);
if(a[i]==b[j]) f[j]=maxn+1;
}
}
for(int i=1;i<=m;++i) ans=max(ans,f[i]);
printf("%d",ans);
return 0;
}
完结撒花!!
yzoj1985 最长公共单调上升子序列 题解的更多相关文章
- 【JZOJ4889】【NOIP2016提高A组集训第14场11.12】最长公共回文子序列
题目描述 YJC最近在学习字符串的有关知识.今天,他遇到了这么一个概念:最长公共回文子序列.一个序列S,如果S是回文的且分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已 ...
- 最长公共子串和子序列的Python实现,带图示。
使用矩阵来记录两个子串之间各个字符之间的对应关系. 最长子串:矩阵中数字最大的就是最长子串的长度.若对应位置字符相同,则c[i][j] = c[i-1][j-1] + 1 def longSubStr ...
- 动态规划 最长公共子序列 LCS,最长单独递增子序列,最长公共子串
LCS:给出两个序列S1和S2,求出的这两个序列的最大公共部分S3就是就是S1和S2的最长公共子序列了.公共部分 必须是以相同的顺序出现,但是不必要是连续的. 选出最长公共子序列.对于长度为n的序列, ...
- SCOJ 4493: DNA 最长公共子串 后缀自动机
4493: DNA 题目连接: http://acm.scu.edu.cn/soj/problem.action?id=4493 Description Deoxyribonucleic acid ( ...
- 【LCS,LIS】最长公共子序列、单调递增最长子序列
单调递增最长子序列 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 求一个字符串的最长递增子序列的长度如:dabdbf最长递增子序列就是abdf,长度为4 输入 ...
- C++版 - Lintcode 77-Longest Common Subsequence最长公共子序列(LCS) - 题解
版权声明:本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C++版 - L ...
- [C++] 动态规划之矩阵连乘、最长公共子序列、最大子段和、最长单调递增子序列、0-1背包
一.动态规划的基本思想 动态规划算法通常用于求解具有某种最优性质的问题.在这类问题中,可能会有许多可行解.每一个解都对应于一个值,我们希望找到具有最优值的解. 将待求解问题分解成若干个子问题,先求解子 ...
- 算法复习周------“动态规划之‘最长公共子序列’”&&《计蒜课》---最长公共子串题解
问题描述: 这个问题其实很容易理解.就是给你两个序列X={x1,x2,x3......xm} Y={y1,y2,y3......ym},要求找出X和Y的一个最长的公共子序列. 例:Xi={A, B, ...
- 题解报告:hdu 1159 Common Subsequence(最长公共子序列LCS)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1159 Problem Description 给定序列的子序列是给定的序列,其中有一些元素(可能没有) ...
随机推荐
- 激活函数、正向传播、反向传播及softmax分类器,一篇就够了!
1. 深度学习有哪些应用 图像:图像识别.物体识别.图片美化.图片修复.目标检测. 自然语言处理:机器创作.个性化推荐.文本分类.翻译.自动纠错.情感分析. 数值预测.量化交易 2. 什么是神经网络 ...
- ElasticSearch6.x版本聚合分析整理
ElasticSearch6.x版本聚合分析整理 ES将聚合分析主要分为如下4类 Bucket,分桶类型,类似SQL中的GROUP BY语法 Metric,指标分析类型,如计算最大值 , 最小值,平均 ...
- 荔枝FM前端面试题
最近接到了荔枝FM的面试通知,遗憾的是没有拿到offer,但是这次面试呢,还是收获很大的,下面就来给大家说说我遇到的面试题 一面 一面是直接发了一套面试题到邮箱,开启了防作弊的,限时20分钟做完,下面 ...
- javaweb基础整理随笔------jstl与el表达式
虽然jsp中可以写java代码,但是现在不推荐这么做. jsp虽然本质是servlet,但是主要作用只是视图,视图的任务就是显示响应,而不是在JSP中做任何关于程序控制和业务逻辑的事情.所以在JSP页 ...
- 11、增强型for循环对二维数组的输出(test8.java)
由于笔者原因,这部分知识,尚不能整理出代码,笔者会好好学习增强型for循环中迭代起的相关知识,在笔者有能力,书写好这段代码后,将对本篇文章,进行二次修改,也同时欢迎大家与笔者交流,共同学习,共同进步. ...
- WebGL简易教程(二):向着色器传输数据
目录 1. 概述 2. 示例:绘制一个点(改进版) 1) attribute变量 2) uniform变量 3) varying变量 3. 结果 4. 参考 1. 概述 在上一篇教程<WebGL ...
- 牛客多校训练第八场G.Gemstones(栈模拟)
题目传送门 题意: 输入一段字符串,字符串中连续的三个相同的字符可以消去,消去后剩下的左右两段字符串拼接,求最多可消去次数. 输入:ATCCCTTG 输出:2 ATCCCTTG(消去CCC)——& ...
- Elasticsearch由浅入深(一)
什么是Elasticsearch 什么是搜索 百度:我们比如说想找寻任何的信息的时候,就会上百度去搜索一下,比如说找一部自己喜欢的电影,或者说找一本喜欢的书,或者找一条感兴趣的新闻(提到搜索的第一印象 ...
- mybatis 源码分析(二)mapper 初始化
mybatis 的初始化还是相对比较复杂,但是作者在初始化过程中使用了多种设计模式,包括建造者.动态代理.策略.外观等,使得代码的逻辑仍然非常清晰,这一点非常值得我们学习: 一.mapper 初始化主 ...
- 解决多字段联合逻辑校验问题【享学Spring MVC】
每篇一句 不要像祥林嫂一样,天天抱怨着生活,日日思考着辞职.得罪点说一句:"沦落"到要跟这样的人共事工作,难道自己身上就没有原因? 前言 本以为洋洋洒洒的把Java/Spring数 ...