KMP的next[]数组的求解是kmp算法的最重要的一步.下面我们来介绍它.
void GetNext(char* p, int next[])
{
int pLen = strlen(p); //求出长度;
next[0] = -1;
int k = -1;
int j = 0;
while (j < pLen - 1)
{
//p[k]表示前缀,p[j]表示后缀
//k=-1是对防止形成死循环;
if (k == -1 || p[j] == p[k]) //匹配时,
{
++k;
++j;
next[j] = k;
}
else //不匹配时;
{
k = next[k]; // 储存当前置
}
}
}
原理对每一种的可能的匹配的情况进行枚举存储与next[]数组中;
举个栗子:ababaa;
可能在 a ,ab ,aba,ababa, 情况停下来next[]算在这些串中的下一次开始位置.
比如aba就从b位置开始匹配;
完整的程序
#include <stdio.h>
#include <string.h>
// MYSELEF KMP 算法;
void Getnext(char *p, int next[])
{
int Plen = strlen(p);
next[0] = -1;
int k = -1;
int j = 0;
while (j < Plen)
{
if (k == -1 || p[k] == p[j])
{
++k;
j++;
next[j] = k;
}
else
k = next[k];
// printf("%d %d", j, k);
}
}
int my_kmp(char *T, char *p, int next[])
{
int j=0, d=0;
while (j < strlen(T) && d < strlen(p))
{
// d=-1 防止在 首位不相等和,的情况下的死循环;
if (d = -1 || T[j] == p[d]){ //匹配了才加的;
d++;
j++;
}
else
d = next[d] ;//,利用相同的真前缀和真后缀对子串进行调整;
}
if (j > strlen(p)) {
return j - strlen(p); //返回位号;
}
else
return 0;
}
int main()
{
char T[100];
char S[100];
int Next[100], n;
gets(T); //主串;
gets(S); //子串
Getnext(S, Next);
n = my_kmp(T, S, Next);
printf("%d", n);
}
举个栗子;
T : abcabcb
s : abcb;
Getnext(s);
next[]={-1 , 0 ,0 ,0,-1} //代表在不匹配时的下一次字串该从哪里开始;
n=my_kmp(T,p,next);
第一轮: abc 匹配;j=3
取出next[3]=0;
所以下一次的从S[0]开始和匹配在此过程种j不变,因为在abc中bc 都与a不同;
接下来相似;
XXXXaXXX
XXXXb
在a处失配时;x 为相同的真前缀和真后缀 ,即从X的后一位开始于a比较;
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。