题意:输入两个数串,问第二个数串在第一个里面的位置,不存在返回-1;
KMP最难理解的我认为是下一个数组的求解只要稍微了解过就会知道KMP算法是匹配字符串失败时想办法跳过重复的匹配。;
1 2 3 1 2 4要匹配到1 2 3 1 2 3 1 2 3 1 2 4暴力就是一个一个枚举到结尾,但是你发现,这字符串匹配到第二个三时如果可以从子串中3开始就省下几次匹配。
NEXT数组求解
void getNEXT(char str2[])
{
NEXT[0]=-1;
int j=0;
int k=-1;
while(j<len2)
{
if(k==-1||str2[j]==str2[k]){j++;k++;NEXT[j]=k;}
else{k=NEXT[k];}
}
}
然后就是KMP的方法
int KMP()
{
getNEXT();
int i=0,j=0;
while(i<len1)
{
if(j==-1||suzu1[i]==suzu2[j]){i++;j++;}
else{j=NEXT[j];}
if(j==len2)return i;
}
return -1;
}
最后贴一下辣鸡代码
#include <iostream>
#include <string>
#include <cstring>
#include <stdio.h>
#include <math.h>
#include <map>
#define sd(qwe) scanf("%d",&qwe)
#define ss(asd) scanf("%s",asd)
#define sc(xcv) scanf("%c",&xcv)
#define xh(ert,rty,tyu) for(int ert=rty;ert<=tyu;ert++)
#define fxh(u,i,o) for(int u=i;u>=o;u--)
using namespace std;
int len1,len2,suzu1[1000005],suzu2[10005],NEXT[10005];
void getNEXT()
{
int j,k;
j=0;k=-1;
NEXT[0]=-1;
while(j<len2)
{
if(k==-1||suzu2[k]==suzu2[j]){k++;j++;NEXT[j]=k;}
else{k=NEXT[k];}
}
}
int KMP()
{
getNEXT();
int i=0,j=0;
while(i<len1)
{
if(j==-1||suzu1[i]==suzu2[j]){i++;j++;}
else{j=NEXT[j];}
if(j==len2)return i;
}return -1;
}
int main()
{
int k;sd(k);
while(k--)
{
sd(len1);sd(len2);
xh(i,0,len1-1)sd(suzu1[i]);
xh(i,0,len2-1)sd(suzu2[i]);
if(KMP()>-1)
printf("%d\n",KMP()-len2+1);
else
printf("%d\n",-1);
}
return 0;
}