KMP(Knuth-Morris-Pratt)算法是一种用于字符串匹配的经典算法,它能够高效地在一个文本串中查找一个模式串,并且在遇到不匹配情况时能够快速回退到之前的状态。与暴力法相比,KMP算法的时间复杂度为O(n + m),其中n和m分别是主串(文本)的长度和模式串的长度。
KMP算法的关键在于利用部分匹配表(也称为失配函数),来避免在不匹配时回溯到过早的位置。通过这种方法,可以更高效地进行字符串匹配操作。
部分匹配表记录了模式串中每一个位置之前的最长相等前后缀长度。这部分信息对于后续的匹配过程非常关键。
以模式串 ABCABD
为例:
完整的部分匹配表如下:
状态 | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
值 | 0 | 1 | 0 | 1 | 2 | 0 |
根据模式串构建部分匹配表。这里以上述模式串 ABCABD
为例,具体生成过程如下:
def build_partial_match_table(pattern):
length = len(pattern)
table = [0] * length
j = 0
for i in range(1, length):
while j > 0 and pattern[i] != pattern[j]:
j = table[j - 1]
if pattern[i] == pattern[j]:
j += 1
table[i] = j
return table
pattern = "ABCABD"
table = build_partial_match_table(pattern)
print("部分匹配表为:", table)
基于构建好的部分匹配表进行字符串匹配:
def kmp_search(text, pattern):
text_len = len(text)
pattern_len = len(pattern)
if text_len < pattern_len:
return -1
partial_match_table = build_partial_match_table(pattern)
j = 0
for i in range(text_len):
while j > 0 and text[i] != pattern[j]:
j = partial_match_table[j-1]
if text[i] == pattern[j]:
j += 1
if j == pattern_len:
return i - pattern_len + 1
return -1
text = "ABABCABD"
pattern = "ABCABD"
index = kmp_search(text, pattern)
print("模式串在主串中的位置为:", index)
假设我们正在开发一个搜索引擎,需要对用户输入的关键词进行快速检索。我们可以利用KMP算法来提高搜索效率。
import re
def kmp_search(text, pattern):
text_len = len(text)
pattern_len = len(pattern)
if text_len < pattern_len:
return -1
partial_match_table = build_partial_match_table(pattern)
j = 0
for i in range(text_len):
while j > 0 and text[i] != pattern[j]:
j = partial_match_table[j-1]
if text[i] == pattern[j]:
j += 1
if j == pattern_len:
return i - pattern_len + 1
return -1
def build_partial_match_table(pattern):
length = len(pattern)
table = [0] * length
j = 0
for i in range(1, length):
while j > 0 and pattern[i] != pattern[j]:
j = table[j-1]
if pattern[i] == pattern[j]:
j += 1
table[i] = j
return table
# 测试用例
text = "ABABCABD"
pattern = "ABCABD"
index = kmp_search(text, pattern)
print("模式串在主串中的位置为:", index)
# 应用到搜索引擎中
query = "查询关键词"
for word in query.split():
position = kmp_search(text, word)
if position != -1:
print(f"找到匹配的单词 '{word}' 在索引 {position}")
KMP算法在实际应用中的优势在于它能够在最坏情况下保证线性时间复杂度,从而大大提升了搜索效率。通过以上实战演练,可以看出KMP算法可以有效应用于多种场景中,特别是在需要频繁进行模式匹配的情况。