https://www.cnblogs.com/maybe2030/p/4633153.html 写的非常明白,留个记录,需要的可以直接进去看
代码记录,getNext就是算那个“部分匹配值”编码的序列,也就是该文中的这个图
查询的直接可以根据这个编码进行跳跃式的查询减少多余匹配的消耗,移动位数 = 已匹配的字符数 - 对应的部分匹配值,下面对应代码记录下“部分匹配值”的计算过程:搜索词是ABCDABD
第一次,进到if中 i = 0 j = 0 next[1] = 0
第二次,走else i = 1 j = -1
第三次,进到if中 i = 2 j = 0 next[2] = 0
第四次,走else i = 2 j = -1
第五次,进到if中 i = 3 j = 0 next[3] = 0
第六次,走else i = 3 j = -1
第七次,进到if中 i = 4 j = 0 next[4] = 0
第八次,进到if中 i = 5 j = 1 next[5] = 1
第九次,进到if中 i = 6 j = 2 next[6] = 2
第十次,走else i = 6 j = -1
第十一次,进到if中 i = 7 j = 0 next[7] = 0
到此计算完ABCDABD的部分匹配序列next=【0,0,0,0,1,2,0】
void getNext(const std::string &p, std::vector<int> &next)
{
next.resize(p.size());
next[0] = -1;
int i = 0, j = -1;
while (i != p.size() - 1)
{
//这里注意,i==0的时候实际上求的是next[1]的值,以此类推
if (j == -1 || p[i] == p[j])
{
++i;
++j;
next[i] = j;
}
else
{
j = next[j];
}
}
}
int kmp(const std::string& s, const std::string& p, const int sIndex = 0)
{
std::vector<int>next(p.size());
getNext(p, next);//获取next数组,保存到vector中
int i = sIndex, j = 0;
while(i != s.length() && j != p.length())
{
if (j == -1 || s[i] == p[j])
{
++i;
++j;
}
else
{
j = next[j];
}
}
return j == p.length() ? i - j: -1;
}