(1)朴素的模式匹配算法
该算法也称为布鲁特--福斯算法,其基本思想是从主串的第一个字符起与模式串的第一个字符比较,若相等,则继续逐一对字符进行后续的比较,否则从主串第二个字符起与模式串的第一个字符重新比较,直到模式串中每个字符依次和主串中一个连续的字符序列相等时为止,此时称为匹配成功。如果不能在主串中找到与模式串相同的子串,则匹配失败。
def Bfs(s: str, t: str, pos:int):
# 查找并返回模式串T在主串S中从pos开始的位置(下标),若T不是S的子串,则返回-1
i, j = pos, 0 # i,j分别用于指出主串字符和模式串字符的位置
sl, tl = len(s), len(t)
while i < sl and j < tl:
if s[i] == t[j]:
i += 1
j += 1
else:
i = i - j + 1 # 主串字符的位置指针回退
j = 0
if j >= tl:
return i - tl
return -1
假设主串和模式串的长度分别为n和m,最好情况下的时间复杂度为O(n+m),最坏情况下的时间复杂度为O(n×m)
(2)改进的模式匹配算法
改进的模式匹配算法又称KMP算法,改进之处在于:每当匹配过程中出现相比较的字符不相等时,不需要回退主串的字符位置指针,而是利用已经得到的“部分匹配”结果将模式串向右滑动尽可能远的距离,再继续进行比较。
https://www.bilibili.com/video/BV1AY4y157yL?share_source=copy_web
class Solution:
def build_next(self, t):
next = [0] # next数组(初始元素一个0)
prefix_len = 0 # 当前共同后缀的长度
i = 1
while i < len(t):
if t[prefix_len] == t[i]:
prefix_len += 1
next.append(prefix_len)
i += 1
else:
if prefix_len == 0:
next.append(prefix_len)
i += 1
else:
prefix_len = next[prefix_len - 1]
return next
def kmp_search(self, s: str, t: str, pos: int):
next = self.build_next(t)
i, j = pos, 0
while i < len(s) and j < len(t):
if s[i] == t[j]: # 字符匹配,两个指针都指针后移
i += 1
j += 1
elif j > 0: # 字符不匹配,根据next跳过模式串前面的一些字符
j = next[j - 1]
else: # 与字串第一个字符就不匹配,主串后移与模式串第一个字符比较
i += 1
if j == len(t):
return i-j
else:
return -1
学习记录自用