算法训练day9-KMP

28. 实现 strStr()

题目

实现 strStr() 函数。

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

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

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

思路

这道题目其实质是考察KMP经典算法的应用。

所以主要在于理解KMP算法的思想及实现。

KMP名字由来,他的三位发明者的首字母:Knuth,Morris和Pratt。

KMP核心思想:当出现字符串不匹配时,回退到已经匹配过得部分字符开始匹配,避免每次从头匹配,从而大大降低了时间复杂度。

KMP中的一些关键概念

前缀:是指不包含最后一个字符的所有以第一个字符开头的连续子串

后缀:是指不包含第一个字符的所有以最后一个字符结尾的连续子串

前缀表:前缀表就是记录模式串的所有字串的最长相等前缀后缀的长度数组。

模式串与前缀表对应位置的数字表示的就是:下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀。

有了以上概念就能利用前缀表来实现字符串的匹配了。

关键在于如何实现next数组(也就是构建前缀表):

有三种方式:

1.next=前缀表

2.next = 前缀表所有元素-1

3.next = 前缀表整体右移1位。

代码实现

采用1next = 前缀表的方式

class Solution {
    //前缀表(不减一)Java实现
    public int strStr(String haystack, String needle) {
        if (needle.length() == 0) return 0;
        int[] next = new int[needle.length()];
        getNext(next, needle);

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

    }
    
    private void getNext(int[] next, String s) {
        int j = 0;
        next[0] = 0;
        for (int i = 1; i < s.length(); i++) {
            while (j > 0 && s.charAt(j) != s.charAt(i)) 
                j = next[j - 1];
            if (s.charAt(j) == s.charAt(i)) 
                j++;
            next[i] = j; 
        }
    }
}

你可能感兴趣的:(java,数据结构与算法,java,开发语言)