题目背景

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;
}

最新文章

  1. entityframework学习笔记--008-实体数据建模基础之继承关系映射TPH
  2. jsp页面输入小写金额转大写
  3. MSSQL 2008错误提示:更改对于登录sa失败
  4. Java线程池的原理及几类线程池的介绍
  5. c# 存档修改 读取 写入
  6. phpmyadmin #2003 无法登录 MySQL服务器的解决方法
  7. 问题.NET--win7 IIS唯一密钥属性“VALUE”设置为“DEFAULT.ASPX”时,无法添加类型为“add”的重复集合
  8. hadoop 2.3 集群总结
  9. C# 关闭窗体立即停止进程
  10. Visual Studio 2017 for Mac 连接Git的奇怪问题
  11. Jenkins代码管理
  12. 2018/09/05《涂抹MySQL》【权限管理】学习笔记(二)
  13. visual studio code 写c++代码
  14. yii 第一步
  15. spark java API 实现二次排序
  16. 【SAP BI】BW如何连接SQLSERVER数据库
  17. 【Detection】R-FCN: Object Detection via Region-based Fully Convolutional Networks论文分析
  18. 【Linux】- 文件基本属性
  19. Divide by Three CodeForces - 792C
  20. 应大数据时代而写了个磁力搜索的网页- WWW.MOVIH.COM 磁力

热门文章

  1. Java8(一)--lambda表达式
  2. 00Extensible Markup Language
  3. 汇编学习pushl, popl
  4. JAVA基础数组
  5. 关于dijkstra的小根堆优化
  6. zabbix部署-版本3.2.6
  7. uWSGI+nginx+django+virtualenv+supervisor部署项目
  8. 使用vuex实现父组件调用子组件方法
  9. (一)U-Boot启动过程--详细版的完全分析
  10. v-on(事件处理)