LCIS 最长上升公共子序列问题
首先点名一个串叫 L1,另一个叫L2。
明显的是一个DP,那么我们来探讨下如何求得答案。
朴素的算法
首先我们定义状态$dp[ i ][ j ]$表示L1中前i个与L2中前j个的最长公共上升子序列。
最外层枚举i,第二层枚举j,那么L1[i]和L2[j]要么相等,要么不相等,分情况讨论。
■ L1[i]=L2[j] 那么我们以当前L1[i]的大小作为某个公共上升子序列的结尾元素,所以我们就需要向前找比这个结尾元素小的元素来接头,就需要找到dp[i-1][k] $(k<j&&a[k]<a[j])$中的最长的公共上升子序列的长度,然后其数列长度+1,就是现在dp[i][j]的值。
■ L[1]!=L2[j]那么这时候我们则需要继承前边最长的序列长度$dp[i][j]=max(dp[i-1][1->j-1])$.
这样的时间复杂度$O(n^2 \times m)$,空间复杂度$O(n \times m)$,比较朴素的一中做法。
代码自行脑补吧。。。。
优化
我们来优化一下上边的算法。
我们每个数在计算的时候,这一行前边的数我们已经都计算过了,在这之间我们完全可以用maxn记录一下最大值,避免再去循环枚举k,直接用maxn就好了。
时间复杂度$O(n \times m)$
void LCIS(){
memset(F,,sizeof(F));
for(int i=;i<=n;i++){
LL maxn = ;
for(int j=;j<=m;j++){
F[i][j] = F[i-][j];
if(a[i]>b[j] && maxn < F[i-][j]) maxn = F[i-][j];
if(a[i] == b[j])
F[i][j] = maxn+;
}
}
LL maxn = ;
for(int j=;j<=m;j++){
if(maxn < F[n][j]) maxn = F[n][j];
}
printf("%lld\n",maxn);
}
空间复杂的也可以通过压维进行优化。
对于每次dp[i][j]的改变我们只需要dp[i-1][1->j-1]中的最大值,压维以后,我们只需要dp[i][1->j-1]中的最大值,同样maxn记录就好了。
你可能会问:
每次我们查询后边的都会用到前边的,前边的改变后对后边的不会有影响么?
不会,因为我们只需要最大值,在这个数改变之前,进行最大值的替换,当它改变后对后边计算没有任何影响。
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
int T,n,m,f[],a[],b[],ans;
int max(int a,int b){ return a>b?a:b; }
int main()
{
freopen("codes.in","r",stdin);
freopen("codes.out","w",stdout);
scanf("%d",&T);
while(T--)
{
ans=;
scanf("%d",&n);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
scanf("%d",&m);
for(int i=;i<=m;i++)scanf("%d",&b[i]);
memset(f,,sizeof(f));
for(int i=;i<=n;i++)
{
int maxn=;
for(int j=;j<=m;j++)
{
if(a[i]>b[j])maxn=max(maxn,f[j]);
if(a[i]==b[j])f[j]=maxn+;
ans=max(ans,f[j]);
}
}
printf("%d\n",ans);
}
fclose(stdin);fclose(stdout);
}
LCIS 最长上升公共子序列问题的更多相关文章
- hdoj1423 最长上升公共子序列
hdoj1423 题目分析: 两个数组a[n1] , b[n2], 求最长上升公共子序列. 我们可用一维存储 f[i] 表示 b 数组以 j 结尾, 与 a[] 数组构成的最长公共上升子序列. 对数组 ...
- 最长公共子序列(LCS)、最长递增子序列(LIS)、最长递增公共子序列(LICS)
最长公共子序列(LCS) [问题] 求两字符序列的最长公共字符子序列 问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字 ...
- 最长连续公共子序列(LCS)与最长递增公共子序列(LIS)
最长公共子序列(不连续) 实际问题中也有比较多的应用,比如,论文查重这种,就是很实际的一个使用方面. 这个应该是最常见的一种了,不再赘述,直接按照转移方程来进行: 按最普通的方式就是,直接构造二维矩阵 ...
- HDU 1423 最长上升公共子序列(LCIS)
题目大意: 给定两个数字数组a[] , b[],在这两个数组中找一个最长的公共上升子序列,输出最长的长度 从别人地方copy的= = LCIS理解: (1)f[i][j] 表示 a的前i,和b串前 j ...
- 求最长连续公共子序列 POJ 3080
Description The Genographic Project is a research partnership between IBM and The National Geographi ...
- 贼有意思[最长上升公共子序列](SAC大佬测试题)
题目描述Awson 最近越来越蠢了,一天就只知道 zyys.他定义了一个 zyys 数列:这个数列满足:1.是另外两个数列 A,B 的公共子序列;2.数列单调递增.现在他有一个问题,我们假设知道两个长 ...
- poj3080Blue Jeans(在m个串中找到这m个串的 最长连续公共子序列)
Description The Genographic Project is a research partnership between IBM and The National Geographi ...
- 一维数组解最长上升公共子序列(LCIS)
#include<bits/stdc++.h> using namespace std; + ; int n,a[maxn],b[maxn],dp[maxn]; int main() { ...
- CSU-1120 病毒(最长递增公共子序列)
你有一个日志文件,里面记录着各种系统事件的详细信息.自然的,事件的时间戳按照严格递增顺序排列(不会有两个事件在完全相同的时刻发生). 遗憾的是,你的系统被病毒感染了,日志文件中混入了病毒生成的随机伪事 ...
随机推荐
- E20170426-gg
recursive adj. 回归的,递归的; removal n. 除去; 搬迁; 免职; 移走; customize vt. 定制,定做; 按规格改制;
- hdoj1272【并查集】
因为是第二遍,所以题目也没怎么看,然后一开始的思路就是如果每次输入两个点的时候判断是不是同一个集合,如果同一个就是No,然后就wa了,想想也是,然后瞄了一下题解,还要判连通-真是蠢死了-多个集合都想不 ...
- Educational Codeforces Round 19 B
Description You are given sequence a1, a2, ..., an of integer numbers of length n. Your task is to f ...
- 生产环境中配置的samba
实验需求: 由于实验室纳新一帮新孩子,搭建samba主要是临时共享一些学习资源的,基本上大家用的都是windows.而且这个服务可以让他们在校园的里的个个角落都可以访问到,所以给挂了学校的公网,不过我 ...
- Varnish快速安装及测试
实验环境: slave-147: 192.168.75.147 slave-148: 192.168.75.148 两台机器均已关闭selinux,关闭iptables. varnish部署 ...
- Spring------自动化装配Bean(三)
上一篇是基于java手动装配bean的实现,这一篇将通过xml手动装配bean来实现. xml配置相对于java配置有点: xml配置更加快捷 但不宜扩展 一.打开application.xml 1. ...
- P1847 轰炸II
题目背景 本题为轰炸数据加强版 题目描述 一个城市遭到了M次轰炸,每次都炸了一个每条边都与边界平行的矩形 在轰炸后,有N个关键点,指挥官想知道,它们有没有受到过轰炸,如果有,被炸了几次,最后一次是第几 ...
- AJPFX浅谈Java新手问题之缺少良好的编程习惯
★随意地命名 有些新手写程序,当需要定义某个变量名(也可能是函数名.类名.包名等)时,随意地一敲键盘,名字就起好了......若干星期后,碰到某 bug,再来看自己写的代码时,心中暗自嘀咕:“这代码是 ...
- [转]Java中实现自定义的注解处理器
Java中实现自定义的注解处理器(Annotation Processor) 置顶2016年07月25日 19:42:49 阅读数:9877 在之前的<简单实现ButterKnife的注解功能& ...
- CF782A Andryusha and Socks
题意: Andryusha is an orderly boy and likes to keep things in their place. Today he faced a problem to ...