luogu P3402 最长公共子序列
Posted Nico&11101001
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu 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
普通N^2算法过不了
考虑nlogn
把a[i]映射成其在a中位置
把b[i]在a[I]中出现的位置做一个映射f
使f数组满足不下降,所求f数组长度即为lcs
#include<map> #include<cstdio> #include<algorithm> using namespace std; map<int,int>mp; inline int read() { int x=0;char c=getchar(); while(c<‘0‘||c>‘9‘)c=getchar(); while(c>=‘0‘&&c<=‘9‘)x=x*10+c-‘0‘,c=getchar() ; return x; } int n,m,f[200010]; int ef_search(int l,int r,int x) { while(l<r) { int mid=l+r>>1; if(x<=f[mid])r=mid; else l=mid+1; } return l; } int main() { n=read();m=read(); for(int i=1;i<=n;i++) mp[read()]=i; int len=0; for(int pos,i=1;i<=m;i++) { pos=mp[read()]; if(!pos)continue; if(pos>f[len])f[++len]=pos; else { f[ef_search(1,len,pos)]=pos; } } printf("%d\n",len); return 0; }
以上是关于luogu P3402 最长公共子序列的主要内容,如果未能解决你的问题,请参考以下文章