Luogu 3402 最长公共子序列(二分,最长递增子序列)

Description

经过长时间的摸索和练习,DJL终于学会了怎么求LCS。Johann感觉DJL孺子可教,就给他布置了一个课后作业:

给定两个长度分别为n和m的序列,序列中的每个元素都是正整数。保证每个序列中的各个元素互不相同。求这两个序列的最长公共子序列的长度。

DJL最讨厌重复劳动,所以不想做那些做过的题。于是他找你来帮他做作业。

Input

第一行两个整数n和m,表示两个数列的长度。

第二行一行n个整数$$a_1,a_2,…,a_n,保证1≤a_i≤10^9$$。

第三行一行m个整数$$b_1,b_2,…,b_m,保证1≤b_i≤10^9$$。

对于40%的数据,n, m≤3000

对于100%的数据,n, m≤300000

Output

一行一个整数,表示两个数列的最长公共子序列的长度。

Sample Input

6 6

1 3 5 7 9 8

3 4 5 6 7 8

Sample Output

4

Http

Luogu:https://www.luogu.org/problem/show?pid=3402

Source

二分

解决思路

这道题的弱化版在这里

因为数据加强了,我们不能使用弱化版中的动态规划方法了。

题目中给出了元素互不相同的条件。我们可以将求最长公共子序列(LCS)转化为求最长递增子序列(LIS)

读入A数组的时候,我们定义一个Map[x]表示数x对应的编号,Map[x]=i;这样就相当于把数组A变成了一个递增的序列。

如果我们把B数组里的数都按照A中的规则转置一下,这个题目就变成求B的最长递增子序列了,具体操作如下:

然后在处理B数组的时候(假设我们现在处理数字x),先让x=Map[x]如果此时x==0则说明原来的数字x并没有在数组A中出现过,所以自然也不会成为最长公共子序列的解,直接舍去即可。

这时我们将找到的最长递增子序列放入一个vector(这里用Arr表示),并保证其有序。若x(这个x是用Map转置后的)比vector里所有元素都大(即比Arr[Arr.size()-1]大),则直接将其放到队尾;否则二分查找第一个比x大的元素并替换之。

相信你也发现了,这个算法的核心思路是贪心,我们可以看到,它是让Arr中的元素尽可能的小,以此来求出最长递增子序列,也就可以求出原题的最长公共子序列。

需要注意的是,用这种算法求最长递增子序列只能求出其长度,Arr中的数不一定就是最后要求的最长递增子序列。(为什么呢?仔细想一想)

PS:这个题目真心坑爹,不仅要用上面的这个算法,读入还必须用getchar()读入优化,就连scanf都会超时,真是……

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
using namespace std; int n,m;
map<int,int> Map;
vector<int> Arr; int read();//读入优化,一定要打 int main()
{
int x;
n=read();
m=read();
for (int i=1;i<=n;i++)
{
//scanf("%d",&x);
Map[read()]=i;
}
for (int i=1;i<=m;i++)//将LCS问题转换为LIS问题,降低时间复杂度
{
//scanf("%d",&x);
x=Map[read()];
if (x==0)
continue;
if ((Arr.size()==0)||(x>Arr[Arr.size()-1]))//如果比其中的都大,直接放到后面
Arr.push_back(x);
else//否则,替换第一个比它大的
*lower_bound(Arr.begin(),Arr.end(),x)=x;
}
cout<<Arr.size()<<endl;//Arr的大小就是最后最长子序列的大小
return 0;
} int read()
{
int x=0;
int k=1;
char ch=getchar();
while (((ch<'0')||(ch>'9')) &&(ch!='-'))
ch=getchar();
if (ch=='-')
{
k=-1;
ch=getchar();
}
while ((ch<='9')&&(ch>='0'))
{
x=x*10+ch-48;
ch=getchar();
}
return x*k;
}

Luogu 3402 最长公共子序列(二分,最长递增子序列)的更多相关文章

  1. 算法设计 - LCS 最长公共子序列&&最长公共子串 &&LIS 最长递增子序列

    出处 http://segmentfault.com/blog/exploring/ 本章讲解:1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度:2. 与之类似但不同的 ...

  2. DP:LCS(最长公共子串、最长公共子序列)

    1. 两者区别 约定:在本文中用 LCStr 表示最长公共子串(Longest Common Substring),LCSeq 表示最长公共子序列(Longest Common Subsequence ...

  3. 删除部分字符使其变成回文串问题——最长公共子序列(LCS)问题

    先要搞明白:最长公共子串和最长公共子序列的区别.    最长公共子串(Longest Common Substirng):连续 最长公共子序列(Longest Common Subsequence,L ...

  4. 《算法导论》读书笔记之动态规划—最长公共子序列 & 最长公共子串(LCS)

    From:http://my.oschina.net/leejun2005/blog/117167 1.先科普下最长公共子序列 & 最长公共子串的区别: 找两个字符串的最长公共子串,这个子串要 ...

  5. 【ZH奶酪】如何用Python计算最长公共子序列和最长公共子串

    1. 什么是最长公共子序列?什么是最长公共子串? 1.1. 最长公共子序列(Longest-Common-Subsequences,LCS) 最长公共子序列(Longest-Common-Subseq ...

  6. C语言 · 最长公共子序列 · 最长字符序列

    算法提高篇有两个此类题目: 算法提高 最长字符序列   时间限制:1.0s   内存限制:256.0MB      最长字符序列 问题描述 设x(i), y(i), z(i)表示单个字符,则X={x( ...

  7. 最长公共子序列&最长公共子串

    首先区别最长公共子串和最长公共子序列  LCS(计算机科学算法:最长公共子序列)_百度百科 最长公共子串,这个子串要求在原字符串中是连续的.而最长公共子序列则并不要求连续. 最长公共子序列: http ...

  8. [Python]最长公共子序列 VS 最长公共子串[动态规划]

    前言 由于原微软开源的基于古老的perl语言的Rouge依赖环境实在难以搭建,遂跟着Rouge论文的描述自行实现. Rouge存在N.L.S.W.SU等几大子评估指标.在复现Rouge-L的函数时,便 ...

  9. 最长公共子序列/子串 LCS(模板)

    首先区分子序列和子串,序列不要求连续性(连续和不连续都可以),但子串一定是连续的 1.最长公共子序列 1.最长公共子序列问题有最优子结构,这个问题可以分解称为更小的问题 2.同时,子问题的解释可以被重 ...

  10. 【转】最长公共子序列(LCS),求LCS长度和打印输出LCS

    求LCS的长度,Java版本: public static int LCS(int[]a,int[] b) { int [][]c=new int[a.length+1][b.length+1]; f ...

随机推荐

  1. 你知道现在有一种新的OCR技术叫“移动端车牌识别”吗?

    核心内容:车牌识别.OCR识别技术.移动端车牌识别.手机端车牌识别.安卓车牌识别.Android车牌识别.iOS车牌识别 一.移动端车牌识别OCR技术研发原理 移动端车牌识别是基于OCR识别的一种应用 ...

  2. Xmpp学习之Smack发送消息JID变乱码

    Xmpp学习之Smack发送消息JID变乱码 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请表明出处:http://www.cnblogs.com/cavalier-/p/6947723 ...

  3. HTML表格表单综合——用户注册表

    今天学习了表格和表单知识,我综合了他们添加了一些拓展知识做了一个用户注册表,以下面代码来整理表格和表单知识: <!DOCTYPE html PUBLIC "-//W3C//DTD XH ...

  4. Markdown常用语法对应

    这是一遍备忘录,当忘记Markdown的语法的时候,就到这里来参照. 第一部分是markdown的语法,紧接着就是该语法的效果. 代码语法高亮 ```javascript function synta ...

  5. 在windows下使用Qt5开发GTK3图形界面应用程序

    首先,去MSYS2官网下载MSYS2环境并安装在C:/mysys64下,我安装的是64位的. 进入MSYS命令行执行: pacman -S mingw-w64-x86_64-gtk3 pacman - ...

  6. Vue的报错:Uncaught TypeError: Cannot assign to read only property 'exports' of object '#<Object>'

    Vue的报错:Uncaught TypeError: Cannot assign to read only property 'exports' of object '#<Object>' ...

  7. NodeJS+Express+MongoDB 简单个人博客系统【Study笔记】

    Blog 个人博客系统 iBlog是在学习NodeJs时候一个练手项目Demo 系统支持用户注册/登录,内容文章查看,评论,后台管理(定制显示的分类版块,进行文章内容添加)超级管理员还可进行用户管理等 ...

  8. NodeJS 实现手机短信验证 模块阿里大于

    1,NodeJS 安装阿里大于模块 切换到项目目录使用npm 安装阿里于模块 npm i node-alidayu --save 2,aliyu官网使用淘宝账户登录 登录阿里大于 https://do ...

  9. C#的命名管道(named pipe)

    命名管道是一种从一个进程到另一个进程用内核对象来进行信息传输.和一般的管道不同,命名管道可以被不同进程以不同的方式方法调用(可以跨权限.跨语言.跨平台).只要程序知道命名管道的名字,发送到命名管道里的 ...

  10. .net 4.0 中的特性总结(五):并行编程

    1.任务并行库 从 .NET Framework 4 开始,TPL 是编写多线程代码和并行代码的首选方法. 但是,并不是所有代码都适合并行化:例如,如果某个循环在每次迭代时只执行少量工作,或它在很多次 ...