给出1-n的两个排列P1和P2,求它们的最长公共子序列。
输入输出格式
输入格式:
第一行是一个数n,
接下来两行,每行为n个数,为自然数1-n的一个排列。
输出格式:
一个数,即最长公共子序列的长度
普通求最长公共子序列的dp[i][j]的方法肯定不行
但这里每个元素的值都是确定的了......
以f[i]表示i长度为i的最长公共子序列的最后一个元素在a和b数组中靠后的那一个的位置,这样贪心肯定是不对的
所以......
记录每个元素在a中的位置,所以这是一个{1,2,......,n}的双射
把b中的元素换成它在a中的位置,只要求一个最长上升子序列就可以了
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int maxn=1e5+7; 5 int n,ans,l,r,mid; 6 int a[maxn],b[maxn],tmp[maxn],f[maxn]; 7 int main(){ 8 cin>>n; 9 for(int i=1;i<=n;i++) cin>>a[i],tmp[a[i]]=i; 10 for(int i=1;i<=n;i++) cin>>b[i],b[i]=tmp[b[i]]; 11 for(int i=1;i<=n;i++){ 12 if(b[i]>f[ans]) f[++ans]=b[i]; 13 else{ 14 l=0,r=ans; 15 while(l<=r){ 16 mid=(l+r)/2; 17 if(b[i]>f[mid])l=mid+1; 18 else r=mid-1; 19 } 20 f[l]=b[i]; 21 } 22 } 23 cout<<ans<<endl; 24 return 0; 25 }