假设读者已经了解了KMP算法的基本原理:
本文目标:给出一种经典代码中next[j]函数求解过程的解释
//KMP算法中next[j] 求解样例
void GetNext(int *next, string p)
{
int j=0,k=-1;
next[0]=-1;
while(j < p.length()-1)
{
if(k == -1 || p[j] == p[k])
{
j++;k++;
next[j] = k;
}
else
{
k = next[k];
}
}
}
如上是KMP算法中next[j]求解的经典代码段:
如上图,根据定义:next[j] == k(k是满足条件里最大的值),且有P[0 ~ k-1] == P[j-k ~ j-1]
1. 假设 P[k] == P[j],则有P[0 ~ k-1] + P[k] == P[j-k ~ j-1] + P[j] ==》 P[0 ~ k] == P[j-k ~ j] ,进而有结论 next[j+1] == k+1.
2. 假设P[k] != P[j],则由于上一条的结论(首先next[j] == k,然后当P[k]==P[j]时,推出next[j+1] == k+1),所以我们无法求取next[j+1]的值,
接下来要做的动作就是从[0,k)里找到一个新的k,使得P[k] == P[j](只有P[k] == P[j]才能求next[j+1])。
如何寻找新的k呢,不妨称之为k',然后使 k = k'就行了。
我们已经知道P[0 ~ k-1] == P[j-k ~ j-1],对于 k' :[0,k) 则有P[k-k'~k-1] == P[j-k'~j-1];且k'也需要同时满足P[0 ~ k'-1] == P[j-k' ~ j-1] 才能使得k'的选择有意义,进而推出P[0 ~ k'-1] ==P[k-k'~k-1],也即k' = next[k]。
最后自然而然有 k = next[k]的存在了!
附测试完整代码-----
#include <iostream>
#include <stdio.h>
using namespace std;
void Getnext(int *next,string p)
{
int j = 0;
int k = -1;
next[0] = -1;
while(j < p.size())
{
if(k == -1 || p[k] == p[j])
{
++j;
++k;
if(p[j] == p[k])
next[j] = next[k];
else
next[j] = k;
}else
k = next[k];
}
}
void bmp_print(string t, string p)
{
int cnt = 0;
int i = 0, j = 0;
int * next = new int[p.size()];
int tSize = 0,pSize = 0;
Getnext(next, p);
tSize = t.size();
pSize = p.size();
while(i < tSize && j < pSize)
{
if(j == -1 || t[i] == p[j])
{
i++;
j++;
}
else
{
j = next[j];
}
if(j == p.size())
{
cout<<"s: "<<i - j <<" e:"<<i-1<<endl;
j = 0;
cnt ++;
}
}
if(cnt == 0)
cout<<"there is no match !"<<endl;
delete next;
}
int main()
{
string a = "aavdaadfavghavdyavdt";
string p = "avd";
bmp_print(a,p);
return 0;
}