Description
给出两个序列a[1],a[2],…,a[n]和b[1],b[2],…,b[m],先要求出最小的k使得a[k]=b[1], a[k+1]=b[2],…,a[k+m-1]=b[m]
Input
第一行为用例组数,每组用例第一行为两个整数n和m表示两个序列的长度,第二行为n个整数表示a序列,第三行为m个整数表示b序列
Output
对于每组用例,如果存在k满足条件则输出最小的k,如果没有则输出-1
Sample Input
2
13 5
1 2 1 2 3 1 2 3 1 3 2 1 2
1 2 3 1 3
13 5
1 2 1 2 3 1 2 3 1 3 2 1 2
1 2 3 2 1
Sample Output
6
-1
Solution
把序列中每个数看作一个字符,此题就转化为在文本串(a序列)中找模式串(b序列)了,这个问题显然可以用kmp算法求解,如果找到匹配标记后直接退出循环即可,如果最后没有标记说明没有匹配
Code
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define maxn 1111111
int a[maxn],b[11111];
int la,lb;
int nex[1111111];
int main()
{
int t;
cin>>t;
while(t--)
{
memset(nex,0,sizeof(nex));
scanf("%d%d",&la,&lb);
for(int i=0;i<la;i++)
scanf("%d",&a[i]);
for(int i=0;i<lb;i++)
scanf("%d",&b[i]);
int flag=-1;
for(int i=0,j=-1;i<=lb;i++,j++)//得到next数组
{
nex[i]=j;
while(~j&&b[i]!=b[j])
j=nex[j];
}
for(int i=0,j=0;i<=la;i++,j++)
{
if(j==lb)//找到匹配
{
flag=i-lb+1;//K值
break;
}
while(~j&&a[i]!=b[j])
j=nex[j];
}
printf("%d\n",flag);
}
return 0;
}