题解 | #kmp算法#

kmp算法

https://www.nowcoder.com/practice/bb1615c381cc4237919d1aa448083bcc

暴力枚举法

时间复杂度:

- 外层循环遍历了所有可能的起始位置,时间复杂度为 O(len(T)-len(S)+1)

- 内层循环遍历了字符串 S 的所有字符,时间复杂度为 O(len(S))

- 总时间复杂度为 O((len(T)-len(S)+1) * len(S)) ------------ 这里不满足题目要求

空间复杂度:

- 使用了常数个变量,空间复杂度为 O(1)

class Solution:
    def find(self , S: str, T: str) -> int:
        # write code here
        res = 0  # 出现的次数
        for i in range(len(T)-len(S)+1):
            temp = T[i:i+len(S)]
            temp_res = 0
            for j in range(len(S)):
                if S[j] == temp[j]:
                    temp_res += 1
                else:
                    break
            if temp_res == len(S):
                res += 1
        return res

KMP算法

求next数组

# 最长公共前后缀,求next数组
class Solution(object):
    def longestCommonPrefixAndSuffix(self, strs):
        n = len(strs)
        next = [0]*n
        j = 0  # 要比较的下标
        i = 1  # 当前的下标
        while i < n:
            if strs[i] == strs[j]:  # 如果当前值与被比较值相等
                j += 1
                next[i] = j
                i += 1
            else: # 当前值与被比较值不相等
                if j > 0:    # 没有匹配到头j>0,j=next[j-1]
                    j = next[j-1]
                elif j == 0: # 匹配到头j=0,当前值next[i] = 0 or =j, 然后当前值索引+1
                    next[i] = 0
                    i += 1
        return next
obj = Solution()
print(obj.longestCommonPrefixAndSuffix('ababcabaa'))    # [0, 0, 1, 2, 0, 1, 2, 3, 1]


# 也可以进一步改进成:
# 最长公共前后缀
class Solution(object):
    def longestCommonPrefixAndSuffix(self, s):
        n = len(s)
        # 构建 next 数组
        next = [0] * n
        j = 0
        for i in range(1, n):
            while j > 0 and s[i] != s[j]:
                j = next[j - 1]
            if s[i] == s[j]:
                j += 1
            next[i] = j
        print(next)
obj = Solution()
print(obj.longestCommonPrefixAndSuffix('ababcabaa'))  # [0, 0, 1, 2, 0, 1, 2, 3, 1]

KMP应用next数组求解

# 计算模板串S在文本串T中出现了多少次
# @param S string字符串 模板串, 子串
# @param T string字符串 文本串, 主串
# @return int整型
class Solution:
    def kmp(self , S: str, T: str) -> int:
        # write code here
        '构造next数组'
        '''伪代码
            if S[i]==S[j]:
                i++,j++,next[i]=j
            elif S[i]!=S[j]
                if j==0, next[i]=0=j,i++
                elif j!=0, j = next[j-1]
        '''
        j = 0 # 被比较的下标,初始化为0
        next = [0]*len(S)
        for i in range(1, len(S)): # i循环下标,初始化为1
            if S[i] == S[j]:
                j += 1
                next[i] = j
            else: 
                if j != 0:
                    while j != 0 and S[i] != S[j]:
                        j = next[j-1]
                else: 
                    next[i] = j
        '子串S去匹配主串T'
        '''伪代码
        如果两个串的对应字符相等,索引都+1
        如果不相等,子串的j=0时,主串的索引i+1;j不等于0时,j = next[j-1]
        如果子串循环完成,次数+1,同时更新j,j = next[j-1]
        '''
        i, j = 0, 0
        res = 0 # 次数
        while i < len(T):
            if T[i] == S[j]:
                i+=1
                j+=1
            else:
                if j > 0:
                    j = next[j-1]
                else: # j == 0, 头一个就匹配失败
                    i += 1
            if j == len(S):
                res += 1 # 出现次数+1
                j = next[j-1]
        return res

全部评论

相关推荐

28小凳也想实习:项目不用一个业务一个轮子吗,刷牛客好多人说要一业务一轮子
点赞 评论 收藏
分享
2024-12-29 15:37
已编辑
西华大学 图像识别
程序员牛肉:去不了,大厂算法卡学历吧
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务