最长公共子序列

最长公共子序列

给出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
", len);
    return 0;
}

但是万一给出的两个序列不是排列呢?例如:图片

以5为例,那么B串中的5就可以代表多个A串中的位置。下面给出两种转换方法:

图片

可以发现,第一种转换方法会导致重复选择。因此要转化成第二种方式。

原文地址:https://www.cnblogs.com/MyNameIsPc/p/7813038.html