KMP算法
前半(思路)
该算法主要用于解决两个字符串的匹配问题,例如:
字符串a:adcadcadcadde 字符串b:adcadde
我们需要找出串b在串a中所在位置的第一个下标,这里的结果就是 6
大部分人首先想到的应该就是暴力求解,使用两个变量aIndex1、bIndex2分别指向串a、串b,这种方法不会出错但是方法的事件复杂度比较高。3
KMP算法中会先生成一个next数组用于记录字符串b中子串的最长公共前后缀4,数组的长度为串b的长度,数组的作用就是当两个字符串比较出现不相等字符的情况时,可以不重新开始从串b的第一个字符开始比较,减少比较次数以及降低时间复杂度。
这里我先给出next数组5[-1, 0, 0, 0, 1, 2, 0]
使用next数组的总体思路和暴力算法类似只是当比较的字符不相同时,我们根据bIndex索引在next数组中对应位置的值,例如:
当bIndex等于5时发现字符不相同,这时我们在next数组中寻找next[5]的值2,然后再和串b中下标为2的字符进行比较,字符相等时就继续比较下一个元素,字符不相等时继续寻找next数组的值,直到值为-1,此时aIndex后移、bIndex恢复变为0.
下面我来讲讲具体的流程:
1、 首先aIndex、bIndex进行一一比较,相等进行第二步;否则进行第三步
2、index++、bIndex++,如果bIndex等于串b的长度6返回**(aIndex-b.length+1)**并结束流程,如果aIndex<a.length则进行第一步;否则结束流程
3、根据bIndex寻找next[bIndex]对应的值并将其值设置给bIndex,如果值为-1,进行第四步;否则进行第一步
4、bIndex=0,进行第一步
如图aIndex、bIndex进行比较直到bIndex等于5时元素不相等,此时查看next[5]的值并将其赋值给bIndex
此时变为如上图所示的这种情况
aIndex、bIndex再次进行比较直到bIndex等于5时,又发现元素不相等,将next[5]的值赋值给bIndex
最后比较完成返回**(aIndex-b.length+1)**结果为:12-7+1=6
由于next数组中记录的是串b从0索引到当前索引下7的字符串的最长公共前后缀的长度,那么当出现元素不匹配情况时,如果串b前面的子串存在公共前后缀,那么公共前后缀的部分也就不需要再次进行比较,由于公共前后缀的长度为next[bIndex],那么bIndex就可以直接从索引为next[bIndex]的地方继续进行比较即可,也就是说bIndex不需要重新变为0,降低比较的次数。所以说当元素不相等时,如果next[bIndex]的值越大,比较的次数也就减少的越多。
直接将bIndex变为2继续进行比较
next数组的求解方法在另一篇文章