KMP模式串匹配

 查询在一个很长n的“文本串”中,给定的很短m的“模式串”的出现有无,次数,位置

复杂度O(n+m) 而不是暴力的O(n*m)
这里对模式串做了一个神奇的移位法则,注意KMP是只针对模式串的操作,不是文本串
我喜欢把kmp叫做“对应的前一项前缀位置”
例如:
KMP记录的是怎么一回事,看图看数据马上就明白了
123123123923123123 ----模式串
000123456000123456 ----对应KMP数组值


还有点模糊?
再来组数据
1231212312
0001212345


根据这两张图总结下:
1.由图二可知,匹配基数为字符串的所有前缀(12,123均为前缀)
2.由图一二对比发现,如果字符串出现与前缀中断匹配的部分,或者自己本身就是前缀的话,那么这些部分的KMP值全部为0
3.如果字符串与前缀匹配一直没有发生中断,那么当前位置KMP值可以承接为离自己最近的前缀KMP值

上代码:

char str[N];
cin>>str+1;
int j=0;
int len=strlen(str+1);
For(i,2,len){
while(j&&str[i]!=str[j+1]) j=kmp[j]; //若发现自己后面的点无法匹配,那就跳为kmp值(前一个前缀值)
if(str[i]==str[j+1]) j++;//直到有东西开始和前缀发生匹配
kmp[i]=j;//承接前一个前缀配对的位置或是指向0
}

接下来直接和文本串匹配其实跟模式串内部匹配没有实质区别:

char text[N];
cin>>text+1;
j=0;
for(int i=1;i<=strlen(text+1);i++)
{
while(j>0&&str[j+1]!=text[i])
j=kmp[j];
if (str[j+1]==text[i]) 
j++;
if (j==len) { //长度符合就输出
cout<<i-len+1<<endl;
j=kmp[j];
}
}
原文地址:https://www.cnblogs.com/planche/p/9384006.html