揭秘KMP、BM、KR算法:优劣对比,助你高效匹配字符串

揭秘KMP、BM、KR算法:优劣对比,助你高效匹配字符串

字符串匹配算法在计算机科学中扮演着重要角色,特别是在文本搜索、数据压缩和模式识别等领域。KMP(Knuth-Morris-Pratt)、BM(Boyer-Moore)和KR(Knuth-Pratt)算法是其中最著名的几种。本文将详细介绍这三种算法的工作原理、优劣对比,并辅以实例,帮助读者更好地理解和应用这些算法。

KMP算法

基本原理

KMP算法由Donald Knuth、James Morris和Vance Pratt共同提出。它的核心思想是避免在匹配失败时回溯原字符串,从而提高效率。

前缀函数:计算一个字符串的前缀和后缀的最长公共前后缀的长度数组。

匹配过程:当发生不匹配时,使用前缀函数来决定下一次匹配的起始位置。

代码示例

def kmp_search(text, pattern):

m = len(pattern)

n = len(text)

lps = [0] * m

compute_lps_array(pattern, m, lps)

i = j = 0

while i < n:

if pattern[j] == text[i]:

i += 1

j += 1

if j == m:

return i - j

elif i < n and pattern[j] != text[i]:

if j != 0:

j = lps[j - 1]

else:

i += 1

return -1

def compute_lps_array(pattern, m, lps):

length = 0

lps[0] = 0

i = 1

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

BM算法

基本原理

Boyer-Moore算法由Robert Boyer和J Strother Moore提出。它通过两种启发式方法来提高匹配效率:坏字符规则和好后缀规则。

坏字符规则:从右向左扫描,当发现不匹配时,尽可能向右移动模式串。

好后缀规则:如果模式串与文本的某个后缀匹配,则将模式串移动到该后缀的长度。

代码示例

def bm_search(text, pattern):

m = len(pattern)

n = len(text)

bad_char = [-1] * 256

build_bad_char_table(pattern, m, bad_char)

s = 0

while s <= n - m:

i = m - 1

while i >= 0 and pattern[i] == text[s + i]:

i -= 1

if i < 0:

return s

else:

shift = bad_char[ord(text[s + i])]

if shift == -1:

shift = m - i - 1

s += shift

return -1

def build_bad_char_table(pattern, m, bad_char):

for i in range(256):

bad_char[i] = -1

for i in range(m):

bad_char[ord(pattern[i])] = i

KR算法

基本原理

Knuth-Pratt算法由Donald Knuth和James Pratt提出。它通过避免回溯来提高匹配效率,类似于KMP算法。

计算部分匹配表:计算模式串的子串的最大公共前后缀的长度数组。

匹配过程:当发生不匹配时,使用部分匹配表来决定下一次匹配的起始位置。

代码示例

def kmp_search(text, pattern):

m = len(pattern)

n = len(text)

lps = [0] * m

compute_lps_array(pattern, m, lps)

i = j = 0

while i < n:

if pattern[j] == text[i]:

i += 1

j += 1

if j == m:

return i - j

elif i < n and pattern[j] != text[i]:

if j != 0:

j = lps[j - 1]

else:

i += 1

return -1

def compute_lps_array(pattern, m, lps):

length = 0

lps[0] = 0

i = 1

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

算法对比

以下是三种算法的优缺点对比:

算法

时间复杂度

空间复杂度

优点

缺点

KMP

O(n + m)

O(m)

避免回溯,效率高

需要额外的空间来存储部分匹配表

BM

O(nm)

O(1)

时间复杂度低,空间复杂度小

在某些情况下效率不如KMP

KR

O(n + m)

O(m)

避免回溯,效率高

需要额外的空间来存储部分匹配表

总结

KMP、BM和KR算法都是高效的字符串匹配算法。在实际应用中,可以根据具体需求选择合适的算法。对于大部分应用场景,KMP和KR算法都是不错的选择,因为它们在平均情况下具有较好的性能。

相关推荐

今晚,决赛!
365bet娱乐场官网备用

今晚,决赛!

📅 11-15 👁️ 9048
【日本工作面試】面試時如何回答「為什麼想來日本?」
365bet娱乐场官网备用

【日本工作面試】面試時如何回答「為什麼想來日本?」

📅 01-26 👁️ 9128
苹果6像素多少?
365bet下注

苹果6像素多少?

📅 07-27 👁️ 5206