题目背景
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
#include <stdio.h> #include <ctype.h> #include <string.h> #include <iostream> #include <string> #include <math.h> #include <vector> #include <queue> #include <algorithm> #include <map> using namespace std; map<int,int>f; int a[300009]; int n,m; int c[400009],d[260000],aa,bb; int lcs() { int w,i,j; for(i=1;i<=n;i++) c[i]=f[a[i]]; int s=1; while(c[s]==0) c[s]=999999,s++; d[1]=c[1]; int t=1; for(i=2;i<=n;i++) { int l=1,r=t,mid; while(l<=r) { mid=(l+r)>>1; 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(); cout<<ans; return 0; }