啥是滚动哈希?

滚动哈希(Rolling Hash)是一种 哈希函数,允许在 O(1) 时间内计算 相邻子串 的哈希值,而不需要重新遍历整个子串。它常用于字符串匹配、子串查找等问题,比如 Rabin-Karp 算法 就是基于滚动哈希的。

在说滚动哈希方法之前,先谈谈一般窗口内哈希值是如何计算的

例如对于字符串hello,那么哈希值是 h a s h C o d e ( h e l l o ) = ( h − a ) ∗ p o w ( 131 , 0 ) + ( e − a ) ∗ p o w ( 131 , 1 ) + ( l − a ) ∗ p o w ( 131 , 2 ) + ( l − a ) ∗ p o w ( 131 , 3 ) + ( o − a ) ∗ p o w ( 131 , 4 ) hashCode(hello)=(h-a)*pow(131, 0)+(e-a)*pow(131, 1)+(l-a)*pow(131, 2)+(l-a)*pow(131, 3)+(o-a)*pow(131,4) hashCode(hello)=(ha)pow(131,0)+(ea)pow(131,1)+(la)pow(131,2)+(la)pow(131,3)+(oa)pow(131,4)

当然由于hash值可能会非常大,所以通常还会进行取模

其中,131 是一个常用的进制基数,a 是字符的起始偏移量(例如,‘a’ 可以为 97),pow(131, i) 表示基数的幂。由于哈希值可能会非常大,通常还会对其进行取模操作,常见的模数 MOD 可能是一个大质数,如 1000000007,用于避免溢出。

滚动哈希的核心概念是什么?

一言以蔽之,滚动哈希即利用前缀和思想简化求取窗口哈希值的方法

请看下面的代码

hashCode(l, r) = ((hash[r] - hash[l - 1] * pow(b, r - l + 1)) % p + p) % p
  1. hash[r] - hash[l - 1] 实际上表示从位置 l 到位置 r 这段子串的哈希值,但直接这样做会有问题,因为哈希值是按位数的权重计算的,低位字符的影响会被高位字符的影响掩盖。所以,我们还需要做一个调整。

  2. 由于哈希是按字符的位权计算的,即字符在字符串中的位置越靠后,其在哈希值中的贡献越大(权重越大)。为了从整体哈希值中去除不需要的部分,需要用到一个幂 pow(b, r - l + 1),其中 b 是基数,r - l + 1 是子串长度

  3. 哈希值很容易溢出,因此我们通常对其进行取模运算,这里使用了模数 p。

    由于计算过程中可能会出现负数,我们需要确保取模后的值是非负的,因此加上了 + p,然后再对 p 取模。

完整的实现

const (
	B   = 31         // 进制
	MOD = 1000000007 // 取模
)

func rollingHash(s string, L int) []int {
	n := len(s)
	if n < L {
		return []int{} 
	}

	hashes := make([]int, n-L+1)
	hash, power := 0, 1

	// 计算第一个子串的hash值
	for i := 0; i < L; i++ {
		hash = (hash*B + int(s[i]-'a'+1)) % MOD
		if i < L-1 {
			power = (power * B) % MOD
		}
	}

	hashes[0] = hash

	// 滚动计算后续子串的hash值
	for i := 1; i <= n-L; i++ {
		// 使用滚动哈希公式计算新子串的哈希值
		hash = (hash - (int(s[i-1]-'a'+1) * power % MOD) + MOD) % MOD
		hash = (hash * B + int(s[i+L-1]-'a'+1)) % MOD
		hashes[i] = hash
	}

	return hashes
}

为什么需要滚动哈希?

  • 文件对比:查找两个文件的相似部分
  • 数据去重:发现重复的数据片段
  • 文件分块:将文件分成小块进行存储
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值