zoukankan      html  css  js  c++  java
  • 算法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];
            }
        }
    
  • 相关阅读:
    在VS中用CLAPACK解决广义特征值问题
    再议:__cdecl与__stdcall 调用约定在动态链接库调用中不同的表现
    类成员析构、虚析构函数、动态生成对象相关的 关于析构顺序的杂谈
    C++ 中dynamic_cast的使用方法
    函数传值 复制构造函数 深度拷贝
    hdoj_1867A + B for you again
    如何判断一个数是否为素数
    hdoj_2087剪花布条
    STL容器之优先队列
    hdoj_4006优先队列的使用
  • 原文地址:https://www.cnblogs.com/impw/p/15517984.html
Copyright © 2011-2022 走看看