题目描述
给出 1,2,\ldots,n1,2,…,n 的两个排列 P_1P1 和 P_2P2 ,求它们的最长公共子序列。
输入格式
第一行是一个数 nn。
接下来两行,每行为 nn 个数,为自然数 1,2,\ldots,n1,2,…,n 的一个排列。
输出格式
一个数,即最长公共子序列的长度。
输入输出样例
输入 #1复制
5
3 2 1 4 5
1 2 3 4 5
输出 #1复制
3
说明/提示
- 对于 50\%50% 的数据, n \le 10^3n≤10^3;
- 对于 100\%100% 的数据, n \le 10^5n≤10^5。
思路:
此题因为数据在10^5,用O(n^2)的方法会爆空间
注意到两个序列的特殊性:全排列,即两序列只是值的顺序不一样。
我们来考虑样例:
a: 3 2 1 4 5
b:1 2 3 4 5
用一个map数组映射每个数字出现的顺序。
a: 3 2 1 4 5
map: 1 2 3 4 5
则b数组通过查map表有
b:1 2 3 4 5
查表后对应值 3 2 1 4 5 ,就转化为了求3 2 1 4 5的最长上升子序列。
我们将求最长公共子序列转化求最长上升子序列的问题了。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100005;
int a[N],b[N],m[N],f[N],n,len;
int main()
{
cin>>n;
for(int i=1; i<=n; i++){
cin>>a[i];
m[a[i]]=i;
}
for(int i=1; i<=n; i++){
cin>>b[i];
}
f[1]=a[b[1]];
len=1;
for(int i=2; i<=n; i++){
if(m[b[i]]>f[len]){
f[++len]=m[b[i]];
}
else{
int k=upper_bound(f+1,f+1+len,m[b[i]])-f;
f[k]=m[b[i]];
}
}
cout<<len<<endl;
return 0;
}