题意:输入n,p,q,数据范围是n*n,p是第一个数组的长度,q是第二个数组的长度,求两个数组的最长相同子序列的长度。特别的是每个数组没有重复的的数据
思路:抓住没有重复数据的这一点、将第一个数组的数据与其下标一一对应,第二个数组的数据与第一个数组相同的数据保留,保留其在第一个数组内的下标,这样就是求最长子序列的问题了。lis算法即可。
感想:这个题重点就是每个数组内的数据没有重复的。然后转化成lis问题,感觉是个很有意思的题!
代码:
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
int T,n,m,p,q,num,x,lis[62505],top,a[62505],b[62505];
int main()
{
scanf("%d",&T);
map<int,int>ma;
for(int pp=1;pp<=T;pp++)
{
num=0;
ma.clear();
scanf("%d%d%d",&n,&p,&q);
for(int i=0;i<=p;i++)
{
scanf("%d",&x);
ma[x]=i;
}
top=0;
lis[0]=-0x3f3f3f3f;
for(int i=0;i<=q;i++)
{
scanf("%d",&a[i]);
if(ma.find(a[i])!=ma.end())
{
b[++num]=ma[a[i]];
}
}
for(int i=1;i<=num;i++)
{
if(b[i]>lis[top]) lis[++top]=b[i];
else
{
int l=1,r=top,mid=-1;
while(1)
{
if((l+r)/2==mid) break;
mid=(l+r)/2;
if(lis[mid]>=b[i]) r=mid;
else l=mid;
}
lis[r]=b[i];
}
// cout<<top<<" "<<a<<endl;
}
printf("Case %d: %d\n",pp,top);
}
}