字符串匹配算法——Leetcode 28 实现strstr

一、暴力解法

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

二 RK算法 利用hashmap

class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        '''RK算法 利用hashmap'''
        def hash_(s,start,end):
            '''每一位ascii码相加'''
            assert start <= end
            res = 0
            for c in s[start:end+1]:
                res += ord(c)
            return res
        
        n = len(haystack)
        m = len(needle)
        if n <= m:
            return 0 if haystack==needle else -1
        # n-m+1个子串
        hash_map = [0] * (n-m+1)
        hash_map[0] = hash_(haystack,0,m-1)
        for i in range(1,n-m+1):
            # i-1 i i+1 ... i+m-2
            #     i i+1 ... i+m-2 i+m-1
            hash_map[i] = hash_map[i-1] - hash_(haystack,i-1,i-1) + hash_(haystack,i+m-1,i+m-1)
        
        # 模式串hash
        hash_p = hash_(needle,0,m-1)
        # 匹配
        for i in range(n-m+1):
            if hash_map[i] == hash_p:
                if haystack[i:i+m] == needle:
                    return i
                else:
                    continue
        return -1

三、KMP算法

class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        '''KMP算法'''
        n = len(haystack)
        m = len(needle)
        if n<=m:
            return 0 if haystack == needle else -1
        
        next_ = self.get_next(needle)
        j = 0
        for i in range(n):
            # 向前遍历,直到不相等回退,所有的i,所有的j 提前找到提前返回
            while j >0 and haystack[i] != needle[j]:
                # 移到公共前后缀的前缀后方,直到相等
                j = next_[j-1] + 1
            if haystack[i] == needle[j]:
                if j == m-1:
                    return i-m+1
                else:
                    j += 1
        return -1
    
    def get_next(self,needle):
        '''next数组
           根据i-1推导i
           次最长公共前后缀的前缀等于最长公共前缀的最长公共前后缀'''
        m = len(needle)
        j = -1
        next_ = [-1] * m
        next_[0] = -1
        for i in range(1,m-1):
            j = next_[i-1]
            while j!= -1 and needle[j+1] != needle[i]:
                # i-1最长公共前缀的最长公共前缀
                j = next_[j]

            if needle[j+1] == needle[i]:
                j += 1
            # 相等后公共前后缀长度+1    
            next_[i] = j 
        return next_
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值