KMP算法

2019-06-09  本文已影响0人  topshi

什么是KMP算法

KMP是三位大牛:D.E.Knuth、J.H.Morris和V.R.Pratt同时发现的。
KMP算法要解决的问题是在字符串中找到模式串的位置。平时常见的关键字搜索,模式串就是关键字,如果它在一个主串中出现,则返回它的具体位置,如果不存在就返回-1。

例子

例如要在主串ABCABCABDJK中找到模式串ABCABD的位置。

模式匹配的暴力求解

直接就跳过很多步了,而这正是KMP算法要做的。

KMP算法求解

在讲KMP算法之前,先讲一讲字符串的前缀和后缀。
例如字符串ABCABD,规定前缀不能包含最后一个字符,后缀不能包含第一个字符。那么字符串ABCABD的前缀有AABABCABCAABCAB;后缀有BCABDCABDABDBDD。最长的前后缀相等的字符串就是AB,因此称2为字符串ABCABD的最长前缀后缀。

如上图,pattern[cn] != pattern[i - 1],那么cn会更新变成cn = next[cn],变成下图位置


此时重复pattern[cn] 和 pattern[i - 1]的比较,显然pattern[cn] == pattern[i - 1],则next[i] = ++cn
(如果cn跳到不能再往前跳,next[i] = 0)

这个过程的代码如下

        next[0] = -1;
        next[1] = 0;
        int cn = 0;
        int i = 2;
        while(i < arr.length){
            if(arr[i - 1] == arr[cn]){
                next[i++] = ++cn;
            }else if(cn > 0){
                cn = next[cn];
            }else{
                next[i++] = 0;
            }
        }

定义两个标记ij,逐一比较,如果str[i] == pattern[j],则i++,j++;如果str[i] != pattern[j],那么就可以使用next数组的信息了,上图的位置str[i] != pattern[j]j位置的最大前缀后缀为3,那么j就跳到3位置继续和stri位置比较下去。特别地,如果刚好j位置是0,也就是next[j] == -1,即第一个位置就不匹配了,那么i指针后移一位,继续。
(循环条件:i < str1.length && j < pattern.length)

上一篇下一篇

猜你喜欢

热点阅读