最长公共子序列
给出1-n的两个排列P1和P2,求它们的最长公共子序列。对于100%的数据,n≤100000。
我们可以发现,我们只关心元素的关系,而不关心元素的大小。所以可以把a数组中的值换成123..n,也就是建立一个对应关系\(map[i]\),表示\(map[a[i]]=i\),那么要找b和a的最长公共子序列,就相当于把b用map转换一下,然后求b的lis。b转换后存的数\(b[i]\)就是在a数组中原数的位置。
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1e5+5;
int n, a[maxn], b[maxn], trans[maxn];
int len, f[maxn], pos;
int main(){
scanf("%d", &n); int x;
for (int i=1; i<=n; ++i){
scanf("%d", &x); trans[x]=i; }
for (int i=1; i<=n; ++i){
scanf("%d", &b[i]); b[i]=trans[b[i]]; }
f[++len]=b[1];
for (int i=2; i<=n; ++i){
pos=upper_bound(f+1, f+len+1, b[i])-f;
if (pos>len) f[++len]=b[i];
else f[pos]=b[i];
}
printf("%d\n", len);
return 0;
}
但是万一给出的两个序列不是排列呢?例如:
以5为例,那么B串中的5就可以代表多个A串中的位置。下面给出两种转换方法:
可以发现,第一种转换方法会导致重复选择。因此要转化成第二种方式。