ACM 选手图解 LeetCode 实现 strStr()

简介: ACM 选手图解 LeetCode 实现 strStr()

大家好呀,我是帅蛋。


今天解决实现 strStr(),KMP 算法实战第一题。我们过这道题来熟悉一下 KMP 算法的使用。


话不说多,我们直接开始!

640.png


   LeetCode 28:实现 strStr()



题意


给你两个字符串 haystack 和 needle,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。


如果不存在则返回 -1。


示例


输入:haystack = “hello”,needle = “ll”。
输出:2


提示


  • 0 <= len(haystack)、len(needle) <= 5 * 10^4。
  • haystack 和 needle 仅由小写英文字符组成


题目解析


水题,难度简单。


题意很简单,就是找模式串在主串中的位置,haystack 为主串,needle 为模式串。


解决此类匹配问题是 KMP 算法的常规操作。


如果还不了解 KMP 算法,可以先去看下面这篇文章:


ACM 选手带你玩转 KMP 算法!


既然是用 KMP,那题解步骤分为两步


  • 先求模式串的 next 数组。
  • 后进行匹配操作。


图解


haystack = “hello”,needle = “ll” 为例。


第一步求模式串 needle 的 next 数组。


下图是模式串 needle 的各个前缀:

640.png

根据我在文章KMP 算法的图解,模式串 needle 的 next 数组为:


640.png

def getNext(self, needle: str):
    # 后缀匹配指向
    i = 0
    # 前缀匹配指向
    j = -1
    # 初始化 next 数组
        next = [-1] * len(needle)
    # 此处 next[0] = -1,所以只需要求剩下的 len(T)-1 个即可
    while i < len(needle) - 1:
        # j == -1 就是找无可找 or 匹配成功,相同前缀长度增加1
        if j == -1 or needle[i] == needle[j]:
            i += 1
            j += 1
            next[i] = j
        # 匹配不成功则在前面的子串中继续搜索,直至找不到(即 j== -1 的情况)
        else:
                j = next[j]
    return next

第二步进行匹配操作。


(1) 初始化主串 i 、模式串 j 指针以及 next 数组。

640.png



i = 0
j = 0
next = self.getNext(needle)

(2) i =0,j = 0, haystack[i] != needle[j],此时令 j = next[j] = -1。

640.png


当 j = -1 时,代表着找无可找,所以 i 和 j 同时向右移动。

640.png

# j == -1 就是找无可找 or 匹配成功,相同前缀长度增加1
if j == -1 or haystack[i] == needle[j]:
    i += 1
    j += 1
# 匹配不成功则用 next(j) 找下一次匹配的位置
else:
    j = next[j]


(3) i =1,j = 0, haystack[i] != needle[j],此时令 j = next[j] = -1。

640.png

j = -1,找无可找,i 和 j 继续向右移动。

640.png

(3) i =2,j = 0, haystack[i] == needle[j],i 和 j 向右移动。

640.png


(4) i =3,j = 1, haystack[i] == needle[j],i 和 j 向右移动。

640.png


(5) i =4,j = 2, 此时 j > len(needle),跳出循环。


此时 j == len(needle),证明模式串 needle 在主串 haystack 中存在,返回模式串在主串中出现的第 1 个位置,即 i - j。

# 如果模式串在主串中存在
if j == len(needle):
    return i - j

假设主串长度为 n,模式串长度为 m。


本题解使用 KMP 算法,时间复杂度为 O(n + m)


因为额外维护了一个 next 数组,所以空间复杂度为 O(m)


代码实现


Python 代码实现


class Solution:
    def getNext(self, needle: str):
        # 后缀匹配指向
        i = 0
        # 前缀匹配指向
        j = -1
        # 初始化 next 数组
        next = [-1] * len(needle)
        # 此处 next[0] = -1,所以只需要求剩下的 len(T)-1 个即可
        while i < len(needle) - 1:
            # j == -1 就是找无可找 or 匹配成功,相同前缀长度增加1
            if j == -1 or needle[i] == needle[j]:
                i += 1
                j += 1
                next[i] = j
            # 匹配不成功则在前面的子串中继续搜索,直至找不到(即 j== -1 的情况)
            else:
                j = next[j]
        return next
    def strStr(self, haystack: str, needle: str) -> int:
        i = 0
        j = 0
        next = self.getNext(needle)
        while i < len(haystack) and j < len(needle):
            # j == -1 找无可找,从 S[i+1] 开始和 T[0] 匹配 or 当匹配成功时,往下匹配。
            if j == -1 or haystack[i] == needle[j]:
                i += 1
                j += 1
            # 匹配不成功则用 next(j) 找下一次匹配的位置
            else:
                j = next[j]
        # 如果模式串在主串中存在
        if j == len(needle):
            return i - j
        else:
            return -1


Java 代码实现

class Solution {
    private void getNext(String p, int next[]) {
        int len = p.length();
        int i = 0;
        int j = -1;
        next[0] = -1;
        while (i < len - 1) {
            if (j == -1 || p.charAt(i) == p.charAt(j)) {
                i++;
                j++;
                next[i] = j;
            } else{
                j = next[j];
            }
        }
    }
    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()) {
            if (j == -1 || haystack.charAt(i) == needle.charAt(j)) {
                i++;
                j++;
            } else {
                j = next[j];
            }
            if (j == needle.length())
                return i - j;
        }
        return -1;
    }
}

图解实现 strStr() 到这就结束辣,是不是感觉还可以?


这道题的图解我模拟的是数组从下标 0 开始的,所以如果你还因为我在【KMP 算法】中说的下面这句话而准备打我的话...

640.png



希望你看了这道题放下手里的刀...

640.jpg


我也希望小宝贝们是真的懂了,毕竟 KMP 这玩意懂了就没啥好害怕的。


而且我听说点赞 + 在看 + 转发的小宝贝可以学的更快哟~


我是帅蛋,我们下次见!



相关文章
|
6月前
|
算法 C++ 索引
leetcode-28:实现 strStr()(字符串匹配,暴力匹配算法和KMP算法)
leetcode-28:实现 strStr()(字符串匹配,暴力匹配算法和KMP算法)
78 0
|
22天前
【LeetCode 21】28. 实现 strStr()
【LeetCode 21】28. 实现 strStr()
30 0
|
5月前
|
SQL 算法 数据可视化
Leetcode第28题:实现 strStr()【python】
Leetcode第28题:实现 strStr()【python】
LeetCode-28 实现strStr() KMP算法的学习
LeetCode-28 实现strStr() KMP算法的学习
|
算法 安全 Java
LeetCode - #28 实现 strStr()
不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。如果大家有建议和意见欢迎在文末留言,我们会尽力满足大家的需求。
|
算法 Java C语言
leetcode:28.实现strStr()
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
75 0
leetcode 28 找出字符串第一个匹配的下标(KMP实现strStr)
leetcode 28 找出字符串第一个匹配的下标(KMP实现strStr)
86 0
leetcode 28 找出字符串第一个匹配的下标(KMP实现strStr)
|
程序员
【Leetcode】225. 用队列实现栈、232. 用栈实现队列
【Leetcode】225. 用队列实现栈、232. 用栈实现队列
109 0
【Leetcode】225. 用队列实现栈、232. 用栈实现队列
|
存储 前端开发 算法
一行代码解决LeetCode实现 strStr()使用JavaScript解题|前端学算法
一行代码解决LeetCode实现 strStr()使用JavaScript解题|前端学算法
160 0
一行代码解决LeetCode实现 strStr()使用JavaScript解题|前端学算法
代码随想录刷题|LeetCode 栈和队列的理论基础 232.用栈实现队列 225. 用队列实现栈
代码随想录刷题|LeetCode 栈和队列的理论基础 232.用栈实现队列 225. 用队列实现栈
代码随想录刷题|LeetCode 栈和队列的理论基础 232.用栈实现队列 225. 用队列实现栈