引言
大家都在海边沙滩上找过贝壳,如果沙滩很小可以一寸一寸地找。但如果面对的是整个海滩,这种笨办法就行不通了。字符串搜索也是一样,在几十KB的文本里,暴力搜索还能应付。但在大数据量的日志文件或整个互联网中搜索,就需要更高级的算法。
今天我们带着这些疑问给大家详细介绍下这些高级字符串算法,了解它们背后的原理。
一、 Rabin-Karp算法
1.1 核心思想
举个例子:警察找人时,不需要把每个人都带回去详细检查,只需要对比指纹。如果指纹匹配,再进一步确认身份。
Rabin-Karp就是这个思路:
- 指纹 = 字符串的哈希值
- 详细检查 = 逐个字符比较
1.2 滚动哈希的原理
这是Rabin-Karp最精妙的部分。我们来看一个具体的例子:
假设我们在文本 "314159" 中搜索 "141",基数为10。
第一轮:计算 “314” 的哈希值
hash = (3 × 10² + 1 × 10¹ + 4 × 10⁰) = 314
第二轮:从 “314” 滑动到 “141”
传统做法是重新计算:(1 × 10² + 4 × 10¹ + 1 × 10⁰) = 141
但滚动哈希这样做:
1. 移除最高位3:314 - 3 × 10² = 14
2. 整体左移:14 × 10 = 140
3. 添加新位1:140 + 1 = 141
看到了吗?我们只用了3次算术运算,而不是3次乘方运算!

1.3 哈希冲突
这里有个关键问题:不同的字符串可能有相同的哈希值。比如:
"ABC"的哈希可能是 123"XYZ"的哈希也可能是 123
这就是哈希冲突。Rabin-Karp的解决方案很实在:哈希匹配后,再逐个字符验证。
def rabin_karp_detailed(text, pattern):
n, m = len(text), len(pattern)
if m == 0: return []
base, modulus = 256, 10**9+7
# 计算最高位权重:base^(m-1) % modulus
highest_power = 1
for _ in range(m-1):
highest_power = (highest_power * base) % modulus
# 计算模式串和第一个窗口的哈希
pattern_hash = 0
window_hash = 0
for i in range(m):
pattern_hash = (pattern_hash * base + ord(pattern[i])) % modulus
window_hash = (window_hash * base + ord(text[i])) % modulus
result = []
# 主循环:滑动窗口
for i in range(n - m + 1):
# 先比较哈希值
if pattern_hash == window_hash:
# 哈希匹配,再逐个字符确认
match = True
for j in range(m):
if text[i+j] != pattern[j]:
match = False
break
if match:
result.append(i)
# 如果不是最后一个窗口,计算下一个窗口的哈希
if i < n - m:
# 滚动哈希:移除旧字符,添加新字符
old_char_value = ord(text[i]) * highest_power
new_char_value = ord(text[i+m])
window_hash = (window_hash - old_char_value) % modulus
window_hash = (window_hash * base + new_char_value) % modulus
# 处理负数
if window_hash < 0:
window_hash += modulus
return result
1.4 现实生活中的案例:图书馆检索系统
想想图书馆怎么找书:
- 先用索引卡(哈希值) 快速找到可能的位置
- 再到书架前(逐个比较) 确认是不是想要的书
这样既快又准,Rabin-Karp也是这个思路。
二、 Boyer-Moore算法
2.1 为什么从后往前比较?
大多数人习惯从左往右阅读,但Boyer-Moore告诉我们:有时候反过来更高效!
思考:
在 "Hello, beautiful World!" 中找 "Word"
如果从左边开始:
Hello, beautiful World!
Word
^ 第3个字符就不匹配
如果从右边开始:
Hello, beautiful World!
Word
^ 第4个字符'd' vs 'l' 不匹配
发现了吗?从右边开始,我们一次就能获得更多信息!
2.2 坏字符规则的底层逻辑
当发现不匹配时,我们问自己:这个"坏字符"在模式串的哪里?
高级字符串算法解析

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



