题意:
求两数字串的最长公共子序列(LCS)。
思路:
LCS的时间复杂度为O(nn),因为数据量大,所以会超时。
又因为数字串互不相同,所以可以LCS转LIS(最长上升子序列),LIS有时间复杂度O(nlog(n))的解法。–二分法
先对第一个数字串进行处理,用map记录下每个值所对应的下标(位置),再处理第二个数字串,将其中在第一个数字串中出现的数字构建一个数组,新数组的值记录的是该数字在第一个数字串里的位置。
最后通过最长上升子序列(LIS)求得答案。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#define inf 0x7fffffff
using namespace std;
int n,p,q,a[90000],dp[90000];
int main()
{
ios::sync_with_stdio(false);
int T,x;
scanf("%d",&T);
for(int k=1;k<=T;k++)
{
map<int,int> m;
memset(dp,0,sizeof(dp));
int num=0;
scanf("%d%d%d",&n,&p,&q);
for(int i=0;i<=p;i++)
{
scanf("%d",&x);
m[x]=i+1;
}
for(int i=0;i<=q;i++)
{
scanf("%d",&x);
if(m[x])
{
a[num++]=m[x];
}
}
dp[0]=a[0];
int len=1;
for(int i=1;i<num;i++)
{
if(dp[len-1]<a[i])
{
dp[len++]=a[i];
}
else
{
int id=lower_bound(dp,dp+len,a[i])-dp;
dp[id]=a[i];
}
}
printf("Case %d: %d\n",k,len);
}
return 0;
}