KMP- 简单的子串匹配

本文介绍了如何在给定的文本串(haystack)中寻找模式串(needle)的第一个匹配位置,通过暴力搜索和KMP算法进行优化。暴力搜索的时间复杂度为O(n*m),空间复杂度为O(1);而KMP算法通过构建前缀表减少比较次数,达到时间复杂度O(n+m),空间复杂度O(m)。
摘要由CSDN通过智能技术生成

Problem: 28. 找出字符串中第一个匹配项的下标

问题描述

输入文本串haystack,和模式串needle,找到文本串中是否存在模式串,若存在输出第一次出现的位置,否则输出-1
例子:输入:haystack=“hello”, needle = “ll”; 输出:2
例子:输入:haystack=“hello”, needle = “aa”; 输出:-1

思路

  1. 暴力搜索:

遍历haystack的每个长度为m的子串,判断它和needle是否相等,其中m是指needle的长度。为加快搜索,在遍历子串和needle第i个位置时若不相等,可以提前退出比较;时间复杂度O(n*m), 空间复杂度O(1)

  1. KMP

为加快搜索,可以先构造模式串needle的前缀表pres,其中前缀表表示该字符串各位置处相等的后缀和前缀最长长度,为方便计算,将pres的i+1位置表示字符串i位置的最长相等前缀后缀长度。最后在实现搜索haystack中needle时。定义两个指针分别从haystack和needle中出发,直到发现不一样的位置,根据pres表快速将j指针回退到下一个可以匹配的位置上,这个位置正好使得needle的j位置前字串和haystack的i位置同长的子串相等,若无该位置,则i,j各往前走一步。如此下去,直到i,j超出范围,由于计算pres需要遍历一次needle,且每次操作可认为只有常数次操作,匹配时同样只需遍历一次haystack,且每次操作只有常数次计算,所以总共时间复杂度为O(n+m),空间复杂度O(m)

复杂度

时间复杂度:

暴力: O ( n ∗ m ) O(n*m) O(nm)
KMP : O ( n + m ) O(n+m) O(n+m)

空间复杂度:

暴力: O ( 1 ) O(1) O(1)
KMP O ( m ) O(m) O(m)

Code

暴力搜索

class Solution:
    def strStr(self, haystack: str, needle: str) ->  int:
        for i in range(len(haystack)- len(needle) + 1):
            flag = 1
            for j in range(len(needle)):
                if haystack[i+j] != needle[j]:
                    flag = 0
                    break
            if flag:
                return i
        return -1

KMP

class Solution:
    def strStr(self, haystack: str, needle: str) ->  int:
        def get_next(str1):
            n = len(str1)
            pres = [-1] * (n +1)
            for i in range(n):
                t = pres[i]
                while str1[i] != str1[t] and t!=-1:
                    t = pres[t]
                pres[i+1] = t + 1 
            return pres
        
        i, j = 0, 0
        pres = get_next(needle)
        while j<len(needle) and i<len(haystack):
            while not haystack[i] == needle[j] and j!=-1:
                j = pres[j]
            i += 1
            j += 1
        if j==len(needle):
            return i-len(needle)
        return -1
  • 24
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值