kmp算法代码实现

317 阅读2分钟

kmp算法代码实现主要分成两部分,一个是getNext()计算next数组, 另外是strStr()字符串匹配过程。

next数组

next数组的作用:在发现字符匹配失败时,可以通过next知道模拟串应该回溯的位置

next数组的含义:模拟串在当前位置与其前面的字符构成的字符串的最长公共前后缀

注:

  • 前缀:从第一个字符开始(必须),到最后一个字符之前的所有字符构成的连续子串为前缀
  • 后缀:从第一个字符之外的字符开始,以最后一个字符结尾的所有字符构成的连续字串为后缀

next数组为什么能起到这个作用:因为找到了最长相等的前缀和后缀,匹配失败的是后缀子串的后面,那么我们找到与其相同的前缀的后面重新匹配就可以了

求next数组

// i:后缀末尾
// j:前缀末尾(同时代表之前的子串最长相等前后缀长度)

// 过程当前指向i、j相等时,当前的子串最长相等前后缀+1;否则j回退,直到i、j指向位置相等,或者j=0

// 为什么要回退:因为要重新找相等前后缀
public void getNext(String needle){
    int j = 0;
    for(int i = 1;i < needle.length(); i++){
        while(j>0 && needle.charAt(i) != needle.charAt(i)){
            j = next[j-1];
        }
        if(needle.charAt(i) == needle.charAt(j)) j++;
        next[i] = j;
    }
}

字符串匹配过程

这个就比较简单了,主要是遍历主串的时候同时遍历模拟串,如果主串和模拟串不匹配,则模拟串通过next数组回退,直到遍历完模板串或者遍历完主串未遍历完模板串

public int strStr(String haystack, String needle) {
    next = new int[needle.length()];
    getNext(needle);

    int hayLen = haystack.length();
    int j = 0;
    for(int i = 0; i < hayLen; i++){
        if(haystack.charAt(i) == needle.charAt(j)){
            j++;
        }
        if(j == needle.length()){
            return i - needle.length() + 1;
        }
        while(j>0 && haystack.charAt(i) != needle.charAt(j)){
            j = next[j - 1];
        }
    }
    return -1;
}