题目链接
思路
第一种 (O(N^2))
用f[i][j]表示第一个排列取到i位和第2个排列取到j位的公共子序列长度
[f[i][j]=max(f[i-1][j],f[i][j-1],f[i-1][j-1])
]
最后一种情况需满足(a[i]==b[i])
对于(50%)的数据,(n≤1000),应该可以过
第二种 (O(n cdot log(n) ))
把a重新标号(1)到(n),把b中和a相同的元素跑一遍最长上升子序列就好了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<string>
#include<cstring>
using namespace std;
inline int read() {
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int n;
int a[100005],lcs[100005];
signed main()
{
cin>>n;
for(int i=1;i<=n;++i)
{
int x;
cin>>x;
a[x]=i;//标记
}
int len=0;
lcs[0]=-999;
for(int i=1;i<=n;++i)
{
int x;
cin>>x;
int now=a[x];
if(now>lcs[len])
{
lcs[++len]=now;
}
else
{
int j=lower_bound(lcs+1,lcs+len+1,now)-lcs;
lcs[j]=now;
}
}
cout<<len;
return 0;
}
关于lower_bound请看这篇博客点这里
手打二分的代码:
#include<bits/stdc++.h>
using namespace std;
int a[100001],c[100001],s;
int main(int argc, char const *argv[])
{
int n,xx;
a[0] = -100000;
cin>>n;
for (int i = 1; i <= n; ++i)
{
scanf("%d",&xx);
a[xx] = i;
}
int t;
for (int i = 1; i <= n; ++i)
{
scanf("%d",&t);
t = a[t];
if (t > c[s])
{
c[++s] = t;
}
else{
int l = 1,h = s,m;
while(l <= h){
m = (l + h) / 2;
if(t > c[m]) l =m + 1;
else h = m - 1;
}
c[l] = t;
}
}
cout<<s<<endl;
return 0;
}