KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。
首先我们要求next[]数组,next[j]的值(也就是k)表示,当P[j] != T[i]时,j指针的下一步移动位置。
kmp算法理解:https://www.cnblogs.com/yjiyjige/p/3263858.html
next数组理解:http://www.cnblogs.com/tangzhengyue/p/4315393.html
hdu1711:
#include<bits/stdc++.h>//hdu1711
#define N 1000025
using namespace std;
int n,m;
int s[N],p[N];
int next2[N];
void getnext()
{
int i=0,j=-1;
next2[0]=-1;
while(i<m)
{
if(j==-1||p[i]==p[j])//j==-1,j已经是最左边的了,所以只能i往右移
{
next2[++i]=++j;//如果p[i]==p[j],呢么在已知p[i-1]==p[j-1]的情况下,next2[i]=next2[i-1]+1;如果p[i-1]!=p[j-1],呢么j=next2[j](递归操作);
}
else {
j=next2[j];
}
}
}
int kmp()
{
int i=0,j=0;
getnext();
while(i<n)
{
if(j==-1||s[i]==p[j])
{
j++;
i++;
}
else j=next2[j];
if(j==m)//已经匹配的长度j和p的长度m相等,就返回i
return i;
}
return -1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%d",&s[i]);
for(int i=0;i<m;i++)
scanf("%d",&p[i]);
if(kmp()==-1)
printf("-1\n");
else printf("%d\n",kmp()-m+1);
}
return 0;
}