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. 细说"回车"和"换行"的故事

    引言 最近在php还有c#以及memcache的shell当中经常看到\r\n的写法,刚开始还没注意, 不过后面感觉这样写有些不对头,\r表示回车  \n表示换行,那这样不是换行了两次吗? 为了解决疑 ...

  2. Ace Admin 使用教程

    (原) 公司项目要换框架,然后丢了一套国外的给我,ace admin,本想着拿来改改,翻翻百度就能用的,可它是国外的啊,国内普及率又不高,没办法,硬着头皮一点点啃英文文档吧. File(文件) 简介: ...

  3. 做一枚精致的程序猿,Fighting!

    这几天我和我们的团队正在做一个公司管理系统的项目,团队分工根据成员的水平高低来分工,这样看似公平,但其实不公平,如此这样一来,那些水平稍不如别人的成员就没有发展的机会?那么问题来了,对于水平稍逊色的程 ...

  4. iOS项目评估报告

    1.整体项目无分层概念,结构混乱,代码耦合严重. 影响:后期扩展困难,维护困难. 解决方案:1.整体采用mvc模式. 2.在原来的基础再抽离出业务层 3.业务层按模块管理,合理分层分包. 4.做好共用 ...

  5. DNS分析之 dnsdict6 使用方法

    基本用法就是: dnsdict6 -d46 -t 10 baidu.com

  6. Leetcode 494 Target Sum 动态规划 背包+滚动数据

    这是一道水题,作为没有货的水货楼主如是说. 题意:已知一个数组nums {a1,a2,a3,.....,an}(其中0<ai <=1000(1<=k<=n, n<=20) ...

  7. JavaScript中for循环的使用详解

    or循环是循环最紧凑的形式,并包含有以下三个重要部分组成: 循环初始化计数器的初始值.初始化语句执行循环开始之前. 测试语句,将测试如果给定的条件是真还是假.如果条件为真,那么将要执行的循环中给定的代 ...

  8. node.js搭建代理服务器请求数据

    1.引入node.js中的模块 var http = require("http"); var url = require("url"); var qs = r ...

  9. Linux配置浮动IP实现WEB高可用

    在高可用集群环境中,一般都需要使用浮动IP来实现web高可用(High Availability). 浮动IP的概念以及为什么需要浮动IP请参考:浮动IP(FLOAT IP) 本篇文章主要讲实际操作步 ...

  10. SDS 链表

    sds定义 struct sdshdr{ int len int free char buf[] } sds和c语言类似,仍然把字符串的末尾加上一个'.0',但是不会计入总长度,也就是不会对len造成 ...