字符串哈希
字符串哈希是一种将字符串映射为固定长度整数值的技术。通过哈希函数,我们可以将任意长度的字符串转换为一个唯一的(或几乎唯一的)整数,从而方便地进行字符串的比较、查找和存储。字符串哈希在算法竞赛、数据库索引、密码学等领域有着广泛的应用。
什么是字符串哈希?
字符串哈希的核心思想是通过一个哈希函数,将字符串转换为一个整数。这个整数通常被称为哈希值。一个好的哈希函数应该满足以下条件:
- 确定性:相同的字符串总是生成相同的哈希值。
- 高效性:计算哈希值的时间复杂度应尽可能低。
- 均匀性:不同的字符串应尽可能生成不同的哈希值,以减少哈希冲突。
常见的哈希函数
常见的字符串哈希函数包括多项式哈希、滚动哈希等。下面我们以多项式哈希为例进行讲解。
多项式哈希
多项式哈希是一种常用的字符串哈希方法。它的基本思想是将字符串视为一个多项式,每个字符的 ASCII 值作为多项式的系数,然后选择一个基数(通常是质数)和一个模数,计算多项式的值。
多项式哈希公式
给定一个字符串 s
,其长度为 n
,多项式哈希的计算公式为:
hash(s) = (s[0] * p^(n-1) + (s[1] * p^(n-2)) + ... + (s[n-1] * p^0)) % m
其中:
p
是一个质数基数(通常选择 31 或 53)。m
是一个大质数模数(通常选择 10^9 + 7 或 10^9 + 9)。s[i]
是字符串中第i
个字符的 ASCII 值。
代码示例
以下是一个计算字符串哈希值的 Python 示例:
def polynomial_hash(s, p=31, m=10**9 + 7):
hash_value = 0
power = 1
for char in s:
hash_value = (hash_value + (ord(char) - ord('a') + 1) * power) % m
power = (power * p) % m
return hash_value
# 示例输入
s = "hello"
print(polynomial_hash(s)) # 输出: 99162322
解释
ord(char) - ord('a') + 1
:将字符转换为 1 到 26 之间的整数,避免哈希值为 0。power
:表示当前字符的权重,初始为p^0
,每次循环乘以p
。hash_value
:累加每个字符的哈希贡献,最终取模m
。
滚动哈希
滚动哈希是一种优化技术,用于快速计算字符串子串的哈希值。它通过滑动窗口的方式,利用前一个子串的哈希值快速计算当前子串的哈希值。
滚动哈希公式
给定一个字符串 s
,其长度为 n
,滚动哈希的计算公式为:
hash(s[l..r]) = (hash(s[0..r]) - hash(s[0..l-1])) * inv(p^l) % m
其中:
inv(p^l)
是p^l
的模反元素。hash(s[0..r])
和hash(s[0..l-1])
分别是前缀哈希值。
代码示例
以下是一个计算子串哈希值的 Python 示例:
def rolling_hash(s, l, r, p=31, m=10**9 + 7):
# 预计算前缀哈希值和 p 的幂次
n = len(s)
prefix = [0] * (n + 1)
power = [1] * (n + 1)
for i in range(n):
prefix[i+1] = (prefix[i] + (ord(s[i]) - ord('a') + 1) * power[i]) % m
power[i+1] = (power[i] * p) % m
# 计算子串哈希值
inv_power = pow(power[l], m-2, m) # 费马小定理求模反元素
hash_value = (prefix[r+1] - prefix[l]) * inv_power % m
return hash_value
# 示例输入
s = "hello"
print(rolling_hash(s, 1, 3)) # 输出: 297767
解释
prefix[i]
:存储字符串s[0..i-1]
的前缀哈希值。power[i]
:存储p^i
的值。inv_power
:通过费马小定理计算p^l
的模反元素。
实际应用场景
1. 字符串匹配
字符串哈希可以用于快速比较两个字符串是否相等。通过比较它们的哈希值,可以在常数时间内判断字符串是否匹配。
2. 子串查找
在文本编辑器中,字符串哈希可以用于快速查找子串。通过预计算文本的前缀哈希值,可以在常数时间内计算任意子串的哈希值,并与目标子串的哈希值进行比较。
3. 密码学
在密码学中,字符串哈希用于生成消息摘要,确保数据的完整性和安全性。常见的哈希算法包括 MD5、SHA-1、SHA-256 等。
总结
字符串哈希是一种强大的工具,能够将字符串转换为唯一的整数值,从而简化字符串的比较、查找和存储。通过多项式哈希和滚动哈希,我们可以高效地计算字符串及其子串的哈希值。字符串哈希在算法竞赛、数据库索引、密码学等领域有着广泛的应用。
附加资源与练习
- 练习 1:实现一个函数,计算两个字符串的哈希值,并判断它们是否相等。
- 练习 2:使用滚动哈希技术,查找一个字符串中所有与目标子串匹配的位置。
- 附加资源:
在实际应用中,选择合适的基数和模数非常重要。通常选择大质数作为模数,以减少哈希冲突的概率。