这题因为长度为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
*/