最长公共子序列

最长公共子序列

给出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串中的位置。下面给出两种转换方法:

图片

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

转载于:https://www.cnblogs.com/MyNameIsPc/p/7813038.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值