算法14 leetcode28 实现 strStr() kmp


用indexOf()就没意思了

题目

实现 strStr() 函数。

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回  -1 。

说明:

当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。

示例 1:

输入:haystack = "hello", needle = "ll"
输出:2
示例 2:

输入:haystack = "aaaaa", needle = "bba"
输出:-1
示例 3:

输入:haystack = "", needle = ""
输出:0

提示:

0 <= haystack.length, needle.length <= 5 * 104
haystack 和 needle 仅由小写英文字符组成

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/top-interview-questions-easy/xnr003/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

我的双指针

和滚动窗口大同小异

class Solution {
    public int strStr(String haystack, String needle) {
        if(needle=="") return 0;
        char[] h=haystack.toCharArray();
        char[] n=needle.toCharArray();

        for(int i=0;i<h.length;i++){
            if(h[i]==n[0]){
                int d=0;
                int a=i;
                for(;((d<n.length)&&a<h.length);a++,d++){
                    if(h[a]!=n[d]) break;
                    else if (d==n.length-1) return a-d;
                }
            }
        }
        return -1;

    }
}

滚动窗口(参考)

class Solution {
    public int strStr(String haystack, String needle) {
        int windowSize = needle.length();
        if (windowSize == 0) {
            return 0;
        }

        int j = 0;
        for (int i = 0; i < haystack.length(); i++) {
            if (haystack.charAt(i) == needle.charAt(j)) {
                if (j == windowSize - 1) {
                    return i - windowSize + 1;
                }
                j++;
            } else {
                i -= j;
                j = 0;
            }
        }

        return -1;
    }
}

参考KMP

想弄明白KMP,这篇文章讲的比较好 https://blog.csdn.net/v_july_v/article/details/7041827

    public int strStr(String haystack, String needle) {
        if (needle.length() == 0)
            return 0;
        int i = 0;
        int j = 0;
        
        int[] next = new int[needle.length()];
        getNext(needle, next);
        while (i < haystack.length() && j < needle.length()) {
            /**
             * 这里j等于-1的时候也只有在下面next数组赋值的时候才会出现,并且只有在数组next[0]的时候才会等于-1,
             其他时候是没有的,这一点要谨记,待会下面求next数组的时候就会用到。这里可以这样来理解,如果j不等于-1,
             并且下标i和j所指向的字符相等,那么i和j分别往后移一位继续比较,这个很好理解,那么如果j==-1的时候,就表示
             就表示前面没有匹配成功的,同时i往后移一位,j置为0(j==-1的时候,j++为0),再从0开始比较。
             */
            if (j == -1 || haystack.charAt(i) == needle.charAt(j)) {
                i++;
                j++;
            } else {
                /**
                 * i = i - j + 1;
                 j = 0;
                 返回到指定的位置,不是返回到匹配失败的下一个位置,这里都好理解,重点是求数组next。
                 这里只要j等于0,在next[j]赋值的之后,j就会等于-1;因为next[0]等于-1
                 */
                j = next[j]; // j回到指定位置
            }
            if (j == needle.length())
                return i - j;
        }
        return -1;
    }

    private void getNext(String p, int next[]) {
        int len = p.length();
        int i = 0;
        int j = -1;
        next[0] = -1;//这个默认的,
        /**
         * 匹配的时候是当前字符的前一个和前面的匹配,所以最后一个是不参与匹配的,可以看strStr方法的注释,
         */
        while (i < len - 1) {
            if (j == -1 || p.charAt(i) == p.charAt(j)) {
                /**
                 * 如果j不等于-1,指定的字符相等,那么i和j要往后移一位,这点很好理解,如果j为-1的时候,i往后移移位,j置为0
                 * 重新开始匹配。next[i]是匹配成功的数量
                 */
                i++;
                j++;
                next[i] = j;
            } else
            /**
             * 关键是这里不好理解,为什么匹配失败要让next[j]等于j,要记住这里的next[j]是指匹配成功的数量,有可能为0,也有可能是其他数.比如
             * 字符串ABCABXYABCABATDM,对应的next数组为{-1	0	0	0	1	2	0	0	1	2	3	4	5	1	0	0	}
             */
                j = next[j];
        }
    }
原文地址:https://www.cnblogs.com/impw/p/15517984.html