UVA - 10635 Prince and Princess (二分法 求最长上升子序列)

本文介绍了一种高效算法来解决最大公共子序列问题。通过重新编号和映射技巧,将问题转化为求最长上升子序列,利用二分查找实现 nlogn 的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大体题意:

给你两个数组,求最大公共子序列的长度?

思路:

数据很大,直接求最大公共子序列会超时!

需要转换 一下,因为题目中说 不会出现重复数字,所以可以给第一个数组 重新编号,那么可以映射到第二个数组,第二个数组没有在第一个数组中出现的就不要了,因为肯定不在公共子序列中!

转换完成之后,公共子序列肯定是第一个数组的子序列,并且第一个数组是严格递增的!因此公共子序列也是严格递增的!

因此问题就转换成了求第二个数组的最长上升子序列!

二分法  nlog n!


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 250*250 + 10;
int a[maxn],b[maxn];
int num[maxn];
int LIS[maxn];
int main(){
	int T,kase = 0;
	scanf("%d",&T);
	while(T--){
		
		int n,p,q;
		scanf("%d %d %d",&n, &p, &q);
		for (int i=0; i <= n*n; ++i)num[i] = -1;
		for (int i = 1; i <= p+1; ++i)scanf("%d",&a[i]);
		for (int i = 1; i <= q+1; ++i)scanf("%d",&b[i]);
		int cnt = 0;
		for (int i = 1; i <= p+1; ++i){
			num[a[i]] = ++cnt;
		}
		cnt = 0;
		for (int i = 1; i <= q+1; ++i){
			if (num[b[i]] == -1)continue;
			a[++cnt] = num[b[i]];
		}
//		for (int i = 1; i <= cnt; ++i)printf("%d ",a[i]);
//		puts("");
		int cur = 1;
		LIS[cur] = a[1];
		for (int i = 2; i <= cnt; ++i){
			if (a[i] > LIS[cur]){
				LIS[++cur] = a[i];
			}else{
				int pos = lower_bound(LIS,LIS+cur,a[i]) - LIS;
				LIS[pos] = a[i];
			}
		}
		printf("Case %d: %d\n",++kase,cur);	
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值