KMP算法是针对字符串查找设计的一种时间复杂度为O(m+n)的一种算法,初学时候理解起来很困难,我的个人学习中认为主要难点在于:
1、没有理解算法的逻辑框架
2、不理解为什么可以通过next数组减少运行中的计算
3、不理解为什么可以通过以下代码来实现对于next数组的赋值,即寻找前后缀数组的相似度。
前两部分的内容很多地方都有详细的解释,我主要解释第三点。
代码及注解:
void cal_next(string str, int *next, int len)
{
next[0] = -1;//相似度为0时规定next值为-1(有的书上规定为0,这里只会影响在kmp函数中的return的值,自行对应即可)
int k = -1;
for (int q = 1; q <= len-1; q++)//q就是字符串的长度,这里就是对字符串进行遍历(有的书上会采用while(q!=len),根据自己的喜好选择即可)
{
while (k > -1 && str[k + 1] != str[q])
/*k>-1是限制进入while的条件,str[k + 1] != str[q]是对比当前的两个字符是否相同,
如果相同那么会直接进入下面的if语句,k++,如果不同则回溯到上一步的k值,接着进行比较,直到k=-1或者出现字符相同;
这里就是实现寻找前后缀相似度的核心;
*/
{
k = next[k];
}
if (str[k + 1] == str[q])
{
k++;
}
next[q] = k;//把最后得到的最长相似度数值给next
}
}
这个寻找next组是建立在上一步已经寻找过的相似度的基础上进行的,因此它对于相似度很高的字符串来说,效率会很高。
缺点就是当出现aaa...ab这种字符串时,在对比到最后一个字符串b的时候,它会一步一步的回溯到第一个a,也就是k=-1时才能跳出循环。(KMP改进法对这种方法做了优化)