首先点名一个串叫 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 最长上升公共子序列问题的更多相关文章

  1. hdoj1423 最长上升公共子序列

    hdoj1423 题目分析: 两个数组a[n1] , b[n2], 求最长上升公共子序列. 我们可用一维存储 f[i] 表示 b 数组以 j 结尾, 与 a[] 数组构成的最长公共上升子序列. 对数组 ...

  2. 最长公共子序列(LCS)、最长递增子序列(LIS)、最长递增公共子序列(LICS)

    最长公共子序列(LCS) [问题] 求两字符序列的最长公共字符子序列 问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字 ...

  3. 最长连续公共子序列(LCS)与最长递增公共子序列(LIS)

    最长公共子序列(不连续) 实际问题中也有比较多的应用,比如,论文查重这种,就是很实际的一个使用方面. 这个应该是最常见的一种了,不再赘述,直接按照转移方程来进行: 按最普通的方式就是,直接构造二维矩阵 ...

  4. HDU 1423 最长上升公共子序列(LCIS)

    题目大意: 给定两个数字数组a[] , b[],在这两个数组中找一个最长的公共上升子序列,输出最长的长度 从别人地方copy的= = LCIS理解: (1)f[i][j] 表示 a的前i,和b串前 j ...

  5. 求最长连续公共子序列 POJ 3080

    Description The Genographic Project is a research partnership between IBM and The National Geographi ...

  6. 贼有意思[最长上升公共子序列](SAC大佬测试题)

    题目描述Awson 最近越来越蠢了,一天就只知道 zyys.他定义了一个 zyys 数列:这个数列满足:1.是另外两个数列 A,B 的公共子序列;2.数列单调递增.现在他有一个问题,我们假设知道两个长 ...

  7. poj3080Blue Jeans(在m个串中找到这m个串的 最长连续公共子序列)

    Description The Genographic Project is a research partnership between IBM and The National Geographi ...

  8. 一维数组解最长上升公共子序列(LCIS)

    #include<bits/stdc++.h> using namespace std; + ; int n,a[maxn],b[maxn],dp[maxn]; int main() { ...

  9. CSU-1120 病毒(最长递增公共子序列)

    你有一个日志文件,里面记录着各种系统事件的详细信息.自然的,事件的时间戳按照严格递增顺序排列(不会有两个事件在完全相同的时刻发生). 遗憾的是,你的系统被病毒感染了,日志文件中混入了病毒生成的随机伪事 ...

随机推荐

  1. 51nod 1069【思维】

    具体思路来自相关讨论 给个不太严谨的证明思路: 第一步:证明路径可逆,也就是如果(a, b) -> (x, y)可行,则(x, y) - > (a, b)可行 这个比较直观,只需要分别由( ...

  2. poj1837【背包】

    题意: 有一根杆子,给出一些杆子上的位置,位置上能放重物,再给出一些重物的重量. 重物都需要被使用,但是位置不一定都要用到. 问你能有多少种方法让这个杆子平衡. 思路: 在位置上是0/1背包思想,取或 ...

  3. Hexo搭建博客教程(3) - 远程部署到GitHub Pages

    本章讲的是如何将本地的个人项目远程部署到 GitHub Pages,涉及到GitHub的项目仓库.Git的使用,以及Hexo的远程部署等. 1. 安装 hexo-deployer-git 插件 想要将 ...

  4. Oracle 正则化

    摘抄自:http://www.cnblogs.com/scottckt/archive/2012/10/11/2719562.html ORACLE中的支持正则表达式的函数主要有下面四个: 1,REG ...

  5. Homebrew 常用命令

    Homebrew 常用命令 Homebrew 介绍 Homebrew也称brew,macOS下基于命令行的最强大软件包管理工具,使用Ruby语言开发.类似于CentOS的yum或者Ubuntu的apt ...

  6. Easy Game LightOJ - 1031

    Easy Game LightOJ - 1031 upd:似乎有复杂度更优越的做法,见http://www.cnblogs.com/hehe54321/p/8431020.html 题意:A和B玩一个 ...

  7. Objective-C和 C++ 混编的要点(转)

    Using C++ With Objective-C苹果的Objective-C编译器允许用户在同一个源文件里自由地混合使用C++和Objective-C,混编后的语言叫Objective-C++.有 ...

  8. 如何轻松实现MySQL数据库的读写分离和负载均衡?

    配置好了 Mysql 的主从复制结构后,我们希望实现读写分离,把读操作分散到从服务器中,并且对多个从服务器能实现负载均衡.读写分离和负载均衡是 Mysql 集群的基础需求,MaxScale 就可以帮着 ...

  9. P3374 【模板】树状数组 1 单点修改与区间查询

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...

  10. 使用cordova把h5应用打包成apk

    由于h5应用开发不是本例重点,因此直接提供一个最简单的h5应用代码,此应用使用vue-cli框架开发 此h5应用叫vue1,用webstrom打开vue1,进行npm install安装引用 vue1 ...