• leetcode-28-实现 strStr() 函数(KMP)


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

    说明:
    当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
    对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。

    查看视频
    油管阿三哥讲KMP查找算法,中英文字幕,人工翻译,简单易懂
    帮你把KMP算法学个通透!(理论篇)

    1. 实现前缀表

    /**
     * 前缀表是用来回退的,记录了当模式串与文本串不匹配时,模式串应该从哪里重新匹配。
     * 前缀表具有告诉我们当前位置匹配失败,跳到之前匹配过的地方的能力。
     * 
     * 模式串与前缀表对应位置的数字表示的就是:下标i之前(包括i)的字符串中,有多大长度的相同前后缀。
     * 
     * next数组就可以是前缀表,但是很多实现都是把前缀表统一减一(或者右移一位,初始位置为-1)之后作为next数组。
     * 这并不涉及到KMP的原理,而是具体实现方式不同嗯,next数组即可以就是前缀表,也可以是前缀表统一减一(或者右移一位,初始位置为-1)。
     * 
     * 下面的 kmpNext 方法是:next数组就是前缀表。
     *
     * @param pattern
     * @return
     */
    private int[] kmpNext(String pattern) {
        int len = pattern.length();
        // 初始化前缀表,与模式串长度相同
        int[] next = new int[len];
        // 规定前缀表第一个元素值为0
        next[0] = 0;
        // i指向后缀终止位置,index指向前缀终止位置即前缀的长度
        int i = 1, index = 0;
        while (i < len) {
            // 如果在pattern上位置i和位置index上的字符相同时,把 index(前缀的长度)+1 赋值给next[i],index和i向前移动一位
            if (pattern.charAt(i) == pattern.charAt(index)) {
                next[i] = index + 1;
                index++;
                i++;
            } else {
                // 如果在pattern上位置i和位置index上的字符不相同时,把前缀的位置index移动到next[index - 1]
                if (index != 0) {
                    index = next[index - 1];
                    // 如果在pattern上位置i和位置index上的字符不相同时,且已经把前缀的位置index移动到next数组第0位置上还是不相等,
                    // 就把next数组位置i上赋值为0,并把i往前移动一位
                } else {
                    next[i] = 0;
                    i++;
                }
            }
        }
        return next;
    }
    

    2. 实现KMP搜索

    private int kmpSerach(String haystack, String needle) {
        int[] next = kmpNext1(needle);
        // hi,ni两个指针分别指向文本串和模式串的开头
        int hi = 0, ni = 0;
        while (hi < haystack.length() && ni < needle.length()) {
            // 如果文本串和模式串分别在hi和ni上元素相同,把hi和ni同时往前移动一位
            if (haystack.charAt(hi) == needle.charAt(ni)) {
                hi++;
                ni++;
            } else { // 当模式串与文本串不等时
                if (ni == 0) { 
                    // 当模式串第一个位置字符与文本串不等时,文本串指针向前移动一位
                    hi++;
                } else {
                    // 把模式串按照next数组向前回溯
                    ni = next[ni - 1];
                }
            }
        }
    
        if (ni == needle.length()) {
            return hi - ni;
        }
    
        return -1;
    }
    
  • 相关阅读:
    stm32 IO模式
    stm32的ADC
    bsp
    stm32的硬件调试设置
    RTC实时时钟
    快手2019笔试题 “回文子串" 解题思路
    C++内存修改器开源代码
    FC游戏修改教程(hack)小白文。
    GLFW+GLEW搭建opengl环境(备忘)
    8086 IO读写操作
  • 原文地址:https://www.cnblogs.com/huangj/p/14790998.html
Copyright © 2020-2023  润新知