题目大意:LCS
思路如下:这题倒是道很简单的题目,但是我还是挺喜欢的,至少学会了种新方法。求LCS,但是普通n^2的算法会超时,我第一次超时之后百度了下,看了看LCS的时间优化,说是结合LIS的nlogn算法,然后就开始想。挺巧的,但是我感觉我的这个方法只适用于数组元素不重复的情况,刚好符合这个~有需要再改吧。a、b数组分别接受两串数据,然后开一个lcs数组,当a[i]=b[j]时,令lcs[i]=j,然后用nlogn的算法求lcs数组的最大上升子序列(汗,我用来模拟栈的数组名叫lis)~即以a数组的元素序列定义一个顺序(1,2,....,n即等同于数组下标),然后用一个新的数组依次记录b数组中与a数组相同的元素的b的下标(lcs[i]=j),i 是第 i 个a数组元素,j 是第 j 个b数组元素。
PS:这题对于Java玩家来说,似乎必须用快速io,用快速io在查找时用二分也好,线性也好,都能过;不用快速io怎么都不能过~
AC代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main//中间有段用/***/括起来的是nlogn算法的二分查找,也能AC,但是本人用的是后面的线性查找,两者都能AC
{
static StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
public static int nextInt()throws IOException {in.nextToken();return (int)in.nval;}
public static void main(String[] args)throws IOException
{
int t=nextInt();
int cas=0;
while((cas++)<t)
{
int n=nextInt();
int p=nextInt();
int q=nextInt();
int a[]=new int[p+2];
int b[]=new int[q+2];
for(int i=1;i<p+2;i++)
a[i]=nextInt();//a是记录第一串数据,把a数组中的每个元素顺次构成数组下标
for(int i=1;i<q+2;i++)
b[i]=nextInt();//b是记录第二串数据,把b中元素与a比对,有相同的就赋值为
int lcs[]=new int[q+2];
for(int i=1;i<q+2;i++)
for(int j=1;j<p+2;j++)
if(b[i]==a[j])
{
lcs[i]=j;
break;
}
int pop=1; int lis[]=new int[q+2];
lis[1]=lcs[1];
for(int i=2;i<q+2;i++)
{
if(lcs[i]>lis[pop])
lis[++pop]=lcs[i];
if(lcs[i]<lis[pop])
{
/*int min=1,max=pop;
for(int mid=(min+max)/2;min<=max;mid=(min+max)/2)
{
if(lcs[i]>lis[mid] && lcs[i]<lis[mid+1])//if(lcs[i]<lis[mid] && lcs[i]>lis[mid-1])这样也行
{
lis[mid+1]=lcs[i];//lis[mid]=lcs[i];
break;
}
if(lcs[i]>lis[mid])
min=mid+1;
if(lcs[i]<lis[mid])
max=mid-1;
}*/
for(int k=pop;k>0;k--)
if(lcs[i]>lis[k-1])
{
lis[k]=lcs[i];
break;
}
}
}
System.out.println("Case "+cas+": "+pop);
}
}
}