leetcode28.实现 strStr()「KMP算法」

1.题目描述

实现 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() 定义相符。

2.解题思路

KMP算法详解:

1.计算next数组

next数组即为match中相同前后缀的最长长度,next[ i ]为match[ 0 ~ i-1 ]中的,不算上i,并且不能是match[ 0 ~ i-1 ]本身。

eg: ptr 'ababaca',next数组有match长度位,即7位

对第一位'a'而言,没有相同前后缀,next[0] = -1

对前两位'ab'而言,next[1] = 0

对前三位'aba'而言,next[2] = 0

以此类推,next为[-1, 0, 0, 1, 2, 3, 0]。 注意‘ababa’中前后缀为aba和aba,前缀不包含最后一位,后缀不包含第0位,意味着前后缀不能等于总长。

这样做有什么好处呢?如下图所示

2.KMP

最上方为str,下方为match,3 4 为match在最后一位a之前的最长相同前后缀(3和4相同)。当match和str匹配到match的最后一位,发现match中最后一位为a,而str的对应为置为c。此时,1和2对应match的最长后缀3和4,所以1和2 相同。如果暴力匹配,应当取str[1]与match从[0]开始匹配,但是有了next,没有必要用暴力匹配的方式,因为中间一定匹配不到,直接在2的开始于3进行匹配即可,也就是说,比较2和3后面的是否相同

我们可以用i,j分别指向两个字符串的头部作为初始化,

当匹配失败时,j要移到的下一个位置k, 即next[j]。

KMP算法。其思想:“利用已知部分匹配这个有效信息,保持i指针不回溯,通过修改j指针(next[j]),让模式串尽量地移动到有效的位置。”

所以,next[j]的值(也就是k)表示,当P[j] != T[i]时,j指针的下一步移动位置

这里为什么不是让j直接移动到0呢?

见下图:

参考:https://blog.csdn.net/CSDNwzl/article/details/88085359

参考:https://blog.csdn.net/u013185349/article/details/82316709

3.代码实现

方法1:

class Solution:
    def getNextArray(self,nums):
        if len(nums) < 2:
            nextArray = []
            nextArray.append(-1)
            return nextArray

        nextArray = [-1 for _ in range(len(nums))]
        nextArray[1] = 0
        cnt = 0
        k = 2
        while k < len(nums):
            if nums[k-1] == nums[cnt]:
                cnt += 1
                nextArray[k] = cnt
                k += 1
            elif cnt > 0:
                cnt = nextArray[cnt]
            else:
                nextArray[k] = 0
                k += 1
        return nextArray
    #KMP
    def strStr(self, haystack: str, needle: str) -> int:
        nextArray = self.getNextArray(needle)
        i = 0
        j = 0
        while i < len(haystack) and j < len(needle):
            if haystack[i] == needle[j]:
                i += 1
                j += 1
            elif nextArray[j] == -1:
                i += 1
            else:
                j = nextArray[j]
        if j == len(needle):
            return i-j
        else:
            return -1

方法2:

class Solution(object):
    def strStr(self, haystack, needle):
        """
        :type haystack: str
        :type needle: str
        :rtype: int
        """
        m=len(haystack)
        n=len(needle)
        if n==0:
            return 0
        if m<n:
            return -1
        for i in range(m-n+1):
            j=0
            for j in range(n):
                if haystack[i+j]!=needle[j]:
                    break
                if j == n-1:
                    return i
        return -1
        
        
            
            

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值