返回
字符串匹配算法:大道至简,代码至美
见解分享
2023-11-20 23:41:47
在计算机科学的世界中,大道至简的原则同样适用。本文将探究字符串匹配算法的精髓,用最简洁优雅的代码实现最强大的功能。
从日常应用到复杂的搜索引擎,字符串匹配算法无处不在。Java 的 indexOf() 方法、JavaScript 的 find()、indexOf() 和 includes() 函数都依赖于底层的字符串匹配算法。
本文将深入揭秘四种字符串匹配算法,从简单到复杂,让您领略算法之美:
1. 暴力匹配算法
暴力匹配算法是最简单直接的算法。它从字符串的开头逐个字符与模式进行比较,直到找到匹配项或遍历完整个字符串。
def暴力匹配(s, p):
for i in range(len(s) - len(p) + 1):
if s[i:i+len(p)] == p:
return i
return -1
2. KMP 算法
KMP 算法(Knuth-Morris-Pratt 算法)在暴力匹配算法的基础上进行了改进。它利用模式的失配信息,在发生失配时快速跳过不必要的比较,从而提高效率。
def KMP(s, p):
n, m = len(s), len(p)
fail = [0] * m
j = 0
for i in range(1, m):
while j > 0 and p[i] != p[j]:
j = fail[j - 1]
if p[i] == p[j]:
j += 1
fail[i] = j
i, j = 0, 0
while i < n:
if p[j] == s[i]:
i += 1
j += 1
elif j > 0:
j = fail[j - 1]
else:
i += 1
if j == m:
return i - j
return -1
3. Boyer-Moore 算法
Boyer-Moore 算法是一种基于模式字符位置查找的算法。它利用模式中的字符位置信息,在发生失配时快速跳过大量不必要的比较,效率比 KMP 算法更高。
def BoyerMoore(s, p):
n, m = len(s), len(p)
last = {}
for i in range(m):
last[p[i]] = i
i = m - 1
while i < n:
j = m - 1
while j >= 0 and s[i] == p[j]:
i -= 1
j -= 1
if j < 0:
return i + 1
i += max(1, j - last.get(s[i], -1))
return -1
4. 有限状态自动机算法
有限状态自动机(FSA)算法是一种基于状态转换的算法。它将字符串匹配的过程转换为状态转换图,通过不同的状态转换来判断是否存在匹配项。
def 有限状态自动机(s, p):
m = len(p)
states = [0] * (m + 1)
x = 0
for j in range(1, m + 1):
while x > 0 and p[x] != p[j]:
x = states[x - 1]
if p[x] == p[j]:
x += 1
states[j] = x
j = 0
for i in range(len(s)):
while j > 0 and s[i] != p[j]:
j = states[j - 1]
if s[i] == p[j]:
j += 1
if j == m:
return i - m + 1
return -1
通过对这四种算法的深入分析,我们领悟了算法之美:大道至简,代码至美。在不同的场景下,选择合适的算法可以极大地提高字符串匹配的效率。