UVA10635- Prince and Princess

题意:有两个长度分别为p + 1和q + 1的序列,每个序列中的各个元素互不相同,且都是1~n^2之间的整数。两个序列的第一个元素均为1.求出A和B的最长公共子序列长度。


思路:本题是LCS问题,但因为p和q可以高达250^2,用O(n ^ 2)的算法会超时。因为序列中的所有元素各不相同,因此可以将A序列中的元素重新编号,然后用B序列中的元素去对应。例如例子中的A = {1, 7, 5, 4, 8, 3, 9}, B = {1, 4, 3, 5, 6, 2, 8, 9}, A重新编号后为{1, 2, 3, 4, 5, 6, 7}, B对应的编号为{1, 4, 6, 3, 0, 0, 5, 7},(0表示不存在该元素)。这样求A和B的LCS变成求解B的LIS。然后用N(log(N))的算法求LIS;


lower_bound()的用法。点击打开链接


#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAXN = 250 * 250;
const int INF = 0x3f3f3f3f;

int S[MAXN], g[MAXN], d[MAXN];
int num[MAXN];
int n, p, q, x, cnt; 

int dp() {
    for (int i = 1; i <= cnt; i++)
        g[i] = INF;
    int ans = 0;
    for (int i = 0; i < cnt; i++) {
        int k = lower_bound(g + 1, g + cnt + 1, S[i]) - g; 
        d[i] = k; 
        g[k] = S[i]; 
        ans = max(ans, d[i]);
    }
    return ans;
}

int main() {
    int cas, t = 1;
    scanf("%d", &cas);
    while (cas--) {
        scanf("%d%d%d", &n, &p, &q); 
        memset(num, 0,sizeof(num));
        for (int i = 1; i <= p + 1; i++) {
            scanf("%d", &x); 
            num[x] = i; 
        }
        cnt = 0;
        for (int i = 1; i <= q + 1; i++) {
            scanf("%d", &x); 
            if (num[x]) 
                S[cnt++] = num[x];
        }

        printf("Case %d: %d\n", t++, dp()); 
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值