题目
Given two sequences of numbers : a[1], a[2], … , a[N], and b[1], b[2], … , b[M] (1 <= M <= 10000, 1 <= N <= 1000000). Your task is to find a number K which make a[K] = b[1], a[K + 1] = b[2], … , a[K + M - 1] = b[M]. If there are more than one K exist, output the smallest
题意
两个数组,如果第二个数组为第一个数组的子串,则输出第一个数组与第二个数组相同时的位置。
思路
这道题是一道标准的KMP算法的运用,基本掌握了KMP算法的人可以轻松AC接下来介绍一下KMP算法
KMP算法
KMP算法一般用于字符串匹配问题,KMP算法的核心为next取值,next为当前位置最长对称前后缀,根据定义可以求得next数组
next数组具体实现代码如下
void getnext()
{
nex[0]=-1;
int k=-1;
int j=0;
while(j<m-1)
{
//b[k]表示前缀,b[j]表示后缀
if(b[j]==b[k]||k==-1)
{
++k;
++j;
if(b[j]!=b[k])
{
nex[j]=k;
}
else
{
//因为不能出现pb[j] = b[ nex[j ]],所以当出现时需要继续递归,k = nex[k] = nex[nex[k]]
nex[j]=nex[k];
}
}
else
{
k = nex[k];
}
}
}
源代码为
#include <iostream>
#include <string.h>
using namespace std;
int nex[500000];
int a[1000050];
int b[1000050];
int n,m;
void getnext()
{
nex[0]=-1;
int k=-1;
int j=0;
while(j<m-1)
{
if(b[j]==b[k]||k==-1)
{
++k;
++j;
if(b[j]!=b[k])
{
nex[j]=k;
}
else
{
nex[j]=nex[k];
}
}
else
{
k = nex[k];
}
}
}
void kmp()
{
int j=0;
int i=0;
int sa=n;
int sb=m;
while(i<sa&&j<sb)
{
if(j==-1||a[i]==b[j])
{
i++;
j++;
}
else
{
j=nex[j];
}
}
if(j==sb)
{
cout<<i-j+1<<endl;
return ;
}
else
{
cout<<"-1"<<endl;
return ;
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
memset(nex,0,sizeof(nex));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
cin>>n>>m;
for(int i=0; i<n; i++)
{
cin>>a[i];
}
for(int j=0; j<m; j++)
{
cin>>b[j];
}
getnext();
kmp();
}
return 0;
}