Bootstrap

Java通过KMP算法实现 strStr()

问题:

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。

解答:

class Solution {
    public int strStr(String haystack, String needle) {
        if (needle.length() == 0) {
            return 0;
        }
        int i = 0; // 主串中的指针
        int j = 0; // 子串中的指针
        int[] next = build_next(needle); // 算出的next数组
        while (i < haystack.length() && j < needle.length()) {
            if (haystack.charAt(i) == needle.charAt(j)) {
                // 字符匹配,指针后移
                i++;
                j++;
            } else if (j > 0) {
                // 字符未匹配,根据 next 跳过子串前面的一些字符
                j = next[j -1];
            } else {
                // 子串第一个字符就未匹配
                i++;
            }
        }
        if (j == needle.length()) {
            // 匹配成功
            return i - j;
        } else {
            // 匹配失败
            return -1;
        }
    }

    private int[] build_next(String needle) {
        int len = needle.length();
        int[] next = new int[len]; // 创建next数组
        next[0] = 0;
        int prefix_len = 0; // 当前共同前后缀的长度
        int i = 1;
        while (i < len) {
            if (needle.charAt(prefix_len) == needle.charAt(i)) { // 检查当前字符和下一个字符是否相同
                 /**
                 * 当前字符和下一个字符相同
                 * 共同前后缀长度加1-->prefix_len++
                 * 将当前共同前后缀长度赋值为数组中-->next[i] = prefix_len
                 * 继续递增-->i++
                 */
                prefix_len++;
                next[i] = prefix_len;
                i++;
            } else if (prefix_len == 0) { // 当前字符和下一个字符相同,检查是否有更短的共同前后缀
                // 没有更短的共同前后缀,next直接设置为0
                next[i] = 0;
                i++;
            } else {
                // 有更短的共同前后缀,直接查询获得
                prefix_len = next[prefix_len - 1];
            }
        }
        return next;
    }
}

想更详细了解KMP算法的可参考:【最浅显易懂的 KMP 算法讲解】

;