当先锋百科网

首页 1 2 3 4 5 6 7

这题因为长度为n*n,n最大为250,所以会O(N^2)的LCS(最长公共子序列)算法会超时。所采用的方法是将LCS问题转成LIS(最长递增子序列),不过有个前提,是集合里的数字要没有重复的,这题符合这个要求,比如两个集合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也对应的变成了B={1,4,6,3,0,0,5,7},0可以不要,因为0代表在A中没出现过,不可能在最长公共子序列里的,所以只留下了{1,4,6,3,5,7},就变成了找最长递增子序列的问题了,然后LIS算法有两种,一种是O(n^2)的,还有一种是O(nlogn)的,用nlogn的算法,可以过

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN=251*252;
int main(int argc,char* argv[]){
	int i,j;
	int num[MAXN];
	int sss[MAXN];
	int d[MAXN];
	int T;
	scanf("%d",&T);
	int kase=0;
	while(T--){
		kase++;
		memset(num,0,sizeof(num));
		int n,p,q;
		scanf("%d %d %d",&n,&p,&q);
		int temp;
		for(i=1;i<=p+1;i++){
			scanf("%d",&temp);
			num[temp]=i;
		}
		int k=0;
		for(i=1;i<=q+1;i++){
			scanf("%d",&temp);
			if(num[temp]){
				sss[k++]=num[temp];	
			}
		}
		d[1]=sss[0];
		int len=1;
		for(i=1;i<k;i++){
			 int m=lower_bound(d+1,d+len,sss[i])-d;
			 d[m]=sss[i];
			 if(m==len)
			 	len++;
		}
		printf("Case %d: %d\n",kase,len);
	}
	return 0;
}

/*
5
5 6 7
1 7 5 4 8 3 9
1 4 3 5 6 2 8 9
Case 1: 1

*/