洛谷P3402 最长公共子序列
题目背景
DJL为了避免成为一只咸鱼,来找Johann学习怎么求最长公共子序列。
题目描述
经过长时间的摸索和练习,DJL终于学会了怎么求LCS。Johann感觉DJL孺子可教,就给他布置了一个课后作业:
给定两个长度分别为n和m的序列,序列中的每个元素都是正整数。保证每个序列中的各个元素互不相同。求这两个序列的最长公共子序列的长度。
DJL最讨厌重复劳动,所以不想做那些做过的题。于是他找你来帮他做作业。
输入输出格式
输入格式:
第一行两个整数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。
输出格式:
一行一个整数,表示两个数列的最长公共子序列的长度。
输入输出样例
输入样例#1:
6 6
1 3 5 7 9 8
3 4 5 6 7 8
输出样例#1:
4
说明
对于40%的数据,n, m≤3000
对于100%的数据,n, m≤300000
【题解】
为什么前面的神牛都用了STL函数upper——bound,我这个小蒟蒻不懂。。。
于是乎,我写了个没用这个STL函数的代码,速度慢到爆(最后一个点0.9s+)。
此题难点是
1、数据范围过大,这需要用不定长数组map(不懂看度娘)
2、此题数据是用来卡AC的,所以要先将其转化为一个子序列(map的映射功能),再用优化算法——LIS的n*logn算法。
3、LIS的n*logn算法:D[i]保留满足F[i] = k的所有A[i]中的最小值。F[i]表示从1到i这一段中以i结尾的最长上升子序列的长度。设当前已经求出的最长上升子序列长度为len。先判断A[i](一个子序列)与D[len],若A[i] > D[len],则将A[i]接在D[len]后将得到一个更长的上升子序列,len = len + 1,D[len+1] = A[i];否则,在D[1]..D[len]中,找到最大的j,满足D[j] < A[i].令k = j + 1,则有D[j] < A[i] <= D[k],将A[i]接在D[j]后将得到一个更长的上升子序列,同时更新D[k] = A[i].最后,len即为所要求的最长上升子序列的长度。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
#include<map>
using namespace std;
map<int,int>f;//不定长数组,相当于一种映射,具体请问度娘
int a[300009]={},n,m,c[400009]={},d[260000]={},aa,bb;
int lcs()
{
int w,i,j;
for(i=1;i<=n;i++)
c[i]=f[a[i]];//c数组记录下第一个子序列中的数在第二个子序列中的位置
int s=1;
while(c[s]==0)//c数组元素为0说明第一个子序列的数在第二个子序列中不存在,即是在第一个子序列有,
//第二个子序列没有的数
c[s]=999999,s++;//先把前面的数二分时扔到最后面,直到发现第一个两子序列共有数为止
//ps:前三句话其实都没必要,只是不剪点枝肯定TLE
d[1]=c[1];//第一个数当然直接放第一个
int t=1;
for(i=2;i<=n;i++)//二分找出一个个公共子序列元素所在位置
{
int l=1,r=t,mid;//因为从1开始,比最小两子序列共有数小的数(如0)被放在d[0]不断覆盖(遗忘)
while(l<=r)
{
mid=(l+r)>>1;//>>1等价于/2
if(d[mid]<c[i])
l=mid+1;
else r=mid-1;
}
d[l]=c[i];
if(l>t)//如果发现找出的位置在最后面,那就加长度
t++;
}
return t;
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int q;
for(int i=1;i<=m;i++)
{
scanf("%d",&q);
f[q]=i;//第二个子序列记录下位置
}
int ans=lcs();//LIS的n*logn算法
cout<<ans<<endl;
return 0;
}
洛谷P3402 最长公共子序列的更多相关文章
- 洛谷P1439 最长公共子序列(LCS问题)
题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数n, 接下来两行,每行为n个数,为自然数1-n的一个排列. 输出格式: 一个数,即最长公共子 ...
- 洛谷 [p1439] 最长公共子序列 (NlogN)
可以发现只有当两个序列中都没有重复元素时(1-n的排列)此种优化才是高效的,不然可能很不稳定. 求a[] 与b[]中的LCS 通过记录lis[i]表示a[i]在b[]中的位置,将LCS问题转化为最长上 ...
- P3402 最长公共子序列(nlogn)
P3402 最长公共子序列 题目背景 DJL为了避免成为一只咸鱼,来找Johann学习怎么求最长公共子序列. 题目描述 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子 ...
- P3402 最长公共子序列
P3402 最长公共子序列经典问题LCS-->LIS把第一数列转化成1~n,然后将第二个数列映射成1~n中的一些数,然后求第二个数列的LIS即可,然后用Bit求LIS,O(nlogN) //数据 ...
- luogu P3402 最长公共子序列
题目背景 DJL为了避免成为一只咸鱼,来找Johann学习怎么求最长公共子序列. 题目描述 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子可教,就给他布置了一个课后作 ...
- 洛谷P2766 最长递增子序列问题
https://www.luogu.org/problemnew/show/P2766 注:题目描述有误,本题求的是最长不下降子序列 方案无限多时输出 n 网络流求方案数,长见识了 第一问: DP 同 ...
- 洛谷P4608 [FJOI2016]所有公共子序列问题 【序列自动机 + dp + 高精】
题目链接 洛谷P4608 题解 建个序列自动机后 第一问暴搜 第二问dp + 高精 设\(f[i][j]\)为两个序列自动机分别走到\(i\)和\(j\)节点的方案数,答案就是\(f[0][0]\) ...
- 【Luogu】P3402最长公共子序列(LCS->nlognLIS)
题目链接 SovietPower 的题解讲的很清楚.Map或Hash映射后用nlogn求出LIS.这里只给出代码. #include<cstdio> #include<cctype& ...
- 洛谷 P1439 【模板】最长公共子序列
\[传送门啦\] 题目描述 给出\(1-n\)的两个排列\(P1\)和\(P2\),求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数\(n\), 接下来两行,每行为\(n\)个数,为 ...
随机推荐
- vue组件---组件注册
(1)组件名 在注册一个组件的时候,我们始终需要给它一个名字.比如在全局注册的时候我们已经看到了: Vue.component('my-component-name', { /* ... */ }) ...
- 全局唯一的支付和订单id生成算法
数据库存储的是两个Long类型的复合主键.显示到页面的是一个27位的数字单号 package com.yunyihenkey.common.idworker; /** * * @desc * @aut ...
- vue-quill-editor + element-ui upload实现富文本图片上传
代码贴上 <template> <div class="quill-editor-example"> <div class="box&quo ...
- Servlet的说明及使用案例
Servlet的说明及使用案例 制作人:全心全意 Servle的基础介绍 Servlet结构体系 Servlet对象.ServletConfig对象与Serializable对象是接口对象,其中Ser ...
- svn汉化包安装无效的解决办法
下载svn汉化包要和对应的svn客户端版本对应,否则安装无效, 在安装前要想将svn安装目录下的languages目录下的文件全部删除 还有一点要注意的是 汉化包安装要放在svn安装目录下进行安装,它 ...
- 用Python实现阿里钉钉机器人读取数据库内容自动发群通知
最近想把一些预警数据信息按照一定的要求自动发送到移动端APP,最终把目标放在了腾讯的微信和阿里的钉钉软件上,由于刚开始学习python,于是编程工具想用python来实现.微信使用群体最广,通过一天的 ...
- Windows Server 2008R2服务器IIS安装步骤
注意点: 添加ASP.NET ..NET 扩展性.CGI.ISAPI 扩展.ISAPI 筛选器,去掉 目录浏览(因为大多数网站用不到.) 如果需要用到asp则勾选asp,如果需要用shtm需要开启在服 ...
- mysql执行show processlist unauthenticated user 解决方法
一台unibilling机器前几天突然负载变重. 在top中发现cpu被大量占用. agi程序运行的很慢,并出现僵尸进程. 其实当时只有50个左右的并发呼叫. 远远达不到正常水准. 重新启动机器问题也 ...
- 1827 tarjan+缩点
#include<stdio.h> #include<stack> #include<iostream> #include<string.h> #inc ...
- 输入两个整数n 和m,从数列1,2,3.......n 中任意取几个数, 使其和等于m ,要求将当中全部的可能组合列出来
中兴面试题之中的一个.难度系数中. 题目描写叙述例如以下:输入两个整数n 和m,从数列1,2.3.......n 中任意取几个数, 使其和等于m ,要求将当中全部的可能组合列出来. 逻辑分析: 1.比 ...