https://www.luogu.com.cn/problem/P1439
題目描述
給出1-n的兩個排列P1和P2,求它們的最長公共子序列。
輸入格式
第一行是一個數n,
接下來兩行,每行爲n個數,爲自然數1-n的一個排列。
輸出格式
一個數,即最長公共子序列的長度
輸入輸出樣例
輸入 #1複製
5 3 2 1 4 5 1 2 3 4 5
輸出 #1複製
3
說明/提示
【數據規模】
對於50%的數據,n≤1000
對於100%的數據,n≤100000
【題目分析】這個題首先我們需要想到的是經典的最長公共子序列問題,那麼複雜度爲N^2,可以得到50分,這裏我就直接展示代碼了。
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int a[N],b[N],f[N][N];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int j=1;j<=n;j++) cin>>b[j];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
f[i][j]=f[i-1][j];
if(a[i]==b[j])
{
f[i][j]=max(f[i][j],1);
for(int k=1;k<j;k++)
f[i][j]=max(f[i][j],f[i-1][k]+1);
}
}
int res=0;
for(int i=1;i<=n;i++) res=max(res,f[n][i]);
cout<<res<<endl;
return 0;
}
對於第二個思路是這樣的,我們因爲這是一個1到n的排列,這個其實是對這兩個數組做一個共同的映射,然後求出來一個最長上升子序列就可以了。
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int a[N],q[N],b[N],m[N];
int main()
{
int n;
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],a[i]=m[b[i]];
q[1]=-2e9;
int len=1;
for(int i=1;i<=n;i++)
{
int l=1,r=len;
while(l<r)
{
int mid=l+r+1>>1;
if(q[mid]<a[i]) l=mid;
else r=mid-1;
}
len=max(len,r+1);
q[r+1]=a[i];
}
cout<<len-1<<endl;
return 0;
}