0
点赞
收藏
分享

微信扫一扫

两个数列的最长公共子序列

兽怪海北 2022-03-30 阅读 50
c++蓝桥杯

给出 1∼n 的两个排列 P1​ 和 P2​,求它们的最长公共子序列。

输入格式

第一行是一个数 n (1≤n≤10^5)。

接下来两行,每行为 n 个数,为自然数 1∼n 的一个排列。

输出格式

一个数,即最长公共子序列的长度。

样例解释

输入:

5 
3 2 1 4 5
1 2 3 4 5

输出:

3

 题解:

这里用动态规划会超时,所以就用了个小技巧把问题转换成了求最长上升子序列,然后用二分法就可以了。

#include<iostream>
#include<cstdio>
#define maxn 100003
using namespace std;
int n,x,a[maxn],b[maxn],low[maxn],ans=1;

int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&x);
		a[x]=i;
	}
	for(int i=1;i<=n;i++){
		scanf("%d",&x);
		b[i]=a[x];
		//由此把问题转换为了求最长上升子序列 
		if(i==1) low[1]=b[1];
		else{
			//大的往low数组后面加 
			if(b[i]>low[ans]) low[++ans]=b[i];
			//二分法查找 
		    else{
			    int l=0,r=ans;
			    while(l<r){
				    int mid=l+(r-l)/2;
				    if(low[mid]<b[i]) l=mid+1;
				    else r=mid;
			    }
			    low[l]=b[i];
		    }
		}
	}
	cout<<ans<<endl;
	return 0;
}
举报

相关推荐

0 条评论