LeetCode 28. 实现 strStr()

题目:


实现 strStr() 函数。

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

示例 1:

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

示例 2:

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

说明:

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

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


思路:

从stack那边找到匹配的第一个字符为止,找到继续,找不到跳过继续匹配,当余下长度小于needle 长度则认为找不到返回-1.

方法一:

忍不住想用find..呵呵呵.

class Solution(object):
    def strStr(self, haystack, needle):
        """
        :type haystack: str
        :type needle: str
        :rtype: int
        """
        len_s = len(haystack)
        len_n = len(needle)
        if len_n == 0:
            return 0
        return haystack.find(needle)

方法二:

依次查找,以needle的长度去遍历,找到就返回位置,找不到返回-1,因为是遍历所有长度,所以可以加一个检查,当stack的i位置不等于needle的首字符就跳过,减少时间。

class Solution(object):
    def strStr(self, haystack, needle):
        """
        :type haystack: str
        :type needle: str
        :rtype: int
        """
        len_s = len(haystack)
        len_n = len(needle)
        if len_n == 0:
            return 0
        for i in xrange(len_s-len_n+1):
            if haystack[i] != needle[0]:
                continue
            while (haystack[i:i+len_n] == needle):
                return i
        return -1

或者是双指针移动归位计算,匹配到就返回,匹配不到就依次进一位。

class Solution(object):
    def strStr(self, haystack, needle):
        """
        :type haystack: str
        :type needle: str
        :rtype: int
        """
        len_s, len_n = len(haystack), len(needle)
        if L == 0:
            return 0
        start = 0
        while start < len_s - len_n + 1:
            curr_len = 0
            while curr_len < len_n and haystack[start] == needle[curr_len]:
                start += 1
                curr_len += 1
            if curr_len == len_n:
                return start - len_n
            start = start - curr_len + 1
        return -1

方法三:

KMP算法,研究了好几个博客,终于圆上为什么可以直接移动k....这个解释了。

不过我是说不出来,大概就是知道它为什么要这样写。

记录下KMP算法大佬们的心得。

详解KMP算法

KMP算法最浅显理解——一看就明白

KMP算法next数组的一种理解思路

[KMP算法详解-彻底清楚了(转载+部分原创)]

下面转自提解大大yi-wen-statistics 本题的KMP 算法解释。

方法二中可能存在不少的重复性对比,例如'ABCDFABCDE'与'ABCDE'进行匹配,依照BF算法,需要按顺序逐个比较但实际上第一轮对比过程中发现'E'与'F'不同时可以直接将待匹配字符串向后挪移四格,这样就大大缩短了匹配时间,而KMP的核心思想便在于此——永不回溯。

但还存在一个问题,如果待匹配字符串中出现相同的模式,例如'BBCBBB',且恰好字符库中也存在这样的模式(也可以认为是部分匹配),这时就无法按照上面的方式进行移动了,因此我们还需要一个跳跃数组来辅助我们的对比,我们每次遇到不相同的字符后,就将指针跳跃到后缀字符中部分匹配的位置,这样一来就能避免漏判的情况。

class Solution(object):
    def strStr(self, haystack, needle):
        """
        :type haystack: str
        :type needle: str
        :rtype: int
        """
        n = len(needle)
        m = len(haystack)
        if n == 0: return 0
        j = 0
        pnext = self.getnext(needle)
        for i in range(m):
            while j > 0 and needle[j] != haystack[i]:
                j = pnext[j]
            if needle[j] == haystack[i]:
                j += 1
                if j == n:
                    return i-n+1
        return -1
        
    def getnext(self, s):
        n = len(s)
        pnext = [0, 0] # 多一个前导0是为了方便后续指针跳跃,避免死循环
        j = 0
        for i in range(1, n):
            while j > 0 and s[i] != s[j]:
                j = pnext[j] # 指针跳跃
            if s[j] == s[i]:
                j += 1
            pnext.append(j)
        return pnext
posted @ 2021-01-27 14:42  萧蔷ink  阅读(84)  评论(0编辑  收藏  举报