BF(暴力匹配)算法
BF算法是一种简单的字符串匹配算法,其基本思想是:
- 从主字符串的第一个字符开始,逐个字符与子字符串进行比较。
- 如果当前字符匹配成功,则继续比较下一个字符。
- 如果当前字符匹配失败,则将主字符串的起始位置向后移动一位,重新开始比较。
- 重复上述过程,直到找到匹配的子字符串或遍历完主字符串。
优点:
- 实现简单,易于理解。
缺点:
- 时间复杂度较高,这种算法的时间复杂度为 O((n-m+1) * m),在最坏情况下效率较低,但实现简单,适用于小规模的字符串匹配任务。
代码示例
def bf_search(text, pattern):
n = len(text)
m = len(pattern)
for i in range(n - m + 1):
#range(n - m + 1) 确保了即使 pattern 刚好在 text 的末尾,也能进行匹配检查。
j = 0
#变量 j 用于跟踪当前比较的字符位置。
while j < m and text[i + j] == pattern[j]:
#text[i + j] 表示文本中从位置 i 开始的第 j 个字符,而 pattern[j] 表示模式中的第 j 个字符。通过比较这两个字符,算法逐个字符地检查模式是否与文本中的某个子字符串匹配。
j += 1
if j == m:
return i
#如果 j 达到 m,意味着 pattern 的所有字符都成功匹配,此时返回当前的起始索引 i。
return -1
#如果外层循环结束后仍未找到匹配,则返回 -1,表示 text 中不存在 pattern。
# 测试
text = "abxabcabcaby"
pattern = "abcaby"
print("BF算法匹配结果:", bf_search(text, pattern))
#运行结果
BF算法匹配结果: 6
KMP(Knuth-Morris-Pratt)算法
KMP算法是一种改进的字符串匹配算法,其基本思想是:
- 通过预处理子字符串,构建部分匹配表(LPS数组),记录子字符串的前缀和后缀的最长公共部分。
- 在匹配过程中,利用部分匹配表,避免重复比较,从而提高匹配效率。
步骤:
- 计算子字符串的部分匹配表(LPS数组)。
- 使用部分匹配表进行字符串匹配,避免重复比较。
优点:
- 时间复杂度较低,最坏情况下为O(n+m),其中n是主字符串的长度,m是子字符串的长度。
缺点:
- 实现相对复杂,需要预处理子字符串。
代码示例
def compute_lps(pattern):
m = len(pattern)
lps = [0] * m
#初始化一个长度为 m 的 LPS 数组,所有元素初始值为 0。
length = 0
#初始化一个长度为 m 的 LPS 数组,所有元素初始值为 0。
i = 1
#i = 1 表示从模式字符串 pattern 的第二个字符开始。这是因为第一个字符的 LPS 值总是 0,没有前缀和后缀可以匹配。
while i < m:
if pattern[i] == pattern[length]:
length += 1
lps[i] = length
i += 1
else:
if length != 0:
length = lps[length - 1]#这一步骤避免了重新计算已经匹配的前缀。
else:
lps[i] = 0
i += 1
return lps
def kmp_search(text, pattern):
n = len(text)
m = len(pattern)
lps = compute_lps(pattern)
#函数通过调用compute_lps函数计算模式字符串的最长前缀后缀(LPS)数组。LPS数组用于在模式匹配过程中跳过不必要的字符比较,从而提高搜索效率。
i = 0
j = 0
while i < n:
if pattern[j] == text[i]:#检查当前模式字符串的字符pattern[j]是否与文本字符串的字符text[i]匹配。
i += 1
j += 1
if j == m:#表示模式字符串已经完全匹配,此时返回匹配的起始索引i - j
return i - j
#这两个if语句是独立的,意味着即使第一个if语句的条件不满足,代码仍然会检查第二个if语句的条件。这种结构允许在字符匹配时更新索引,并在模式字符串完全匹配时立即返回匹配的起始位置。
elif i < n and pattern[j] != text[i]:
if j != 0:
j = lps[j - 1]
else:
i += 1
return -1
# 测试
text = "abxabcabcaby"
pattern = "abcaby"
print("KMP算法匹配结果:", kmp_search(text, pattern))
#运行结果
KMP算法匹配结果: 6
总结
-
bf_search(text, pattern):
- 实现了暴力搜索算法。
- 遍历
text
中的每一个子字符串,逐字符比较pattern
。 - 如果找到匹配的子字符串,返回其起始索引;否则返回 -1。
-
compute_lps(pattern):
- 计算模式字符串的最长前缀后缀(LPS)数组。
- LPS 数组用于在 KMP 算法中跳过不必要的字符比较,从而提高搜索效率。
-
kmp_search(text, pattern):
- 实现了 KMP 字符串匹配算法。
- 使用
compute_lps
函数计算模式字符串的 LPS 数组。 - 通过 LPS 数组在模式匹配过程中跳过不必要的字符比较。
- 如果找到匹配的子字符串,返回其起始索引;否则返回 -1。