PrepStack · Markdown HTML

Rolling Hash / Rabin–Karp

字符串匹配、哈希与回文 · HTML

数学 / 逻辑形态

H[i+1]=(H[i]base+code(s[i])) mod M;hash(l,r)=H[r]-H[l]base^(r-l) mod M。

识别信号

容易误判的相似信号

SignalWhy it is different
不能容忍任何概率错误单哈希有碰撞;应双哈希并验证,或用确定性字符串算法。
允许编辑的相似度哈希只判断精确相等,不度量编辑距离。

核心不变量

prefix hash 表示从左到右的多项式;乘幂对齐后,相同子串产生相同指纹。

状态、转移与处理顺序

ItemDefinition
Stateprefix hashes、base 的幂、模数;高可靠场景使用两组独立参数。
Transition扫描追加字符更新前缀;查询用两个前缀相减并乘幂对齐。
Frontier / order预处理前沿逐字符右移;窗口比较只移动端点,不再扫描内部。

Python 骨架

class RollingHash:
    def __init__(self, s, base=911382323, mod=1_000_000_007):
        self.base, self.mod = base, mod
        self.h = [0] * (len(s)+1)
        self.p = [1] * (len(s)+1)
        for i, ch in enumerate(s):
            self.h[i+1] = (self.h[i]*base + ord(ch)+1) % mod
            self.p[i+1] = self.p[i]*base % mod
    def get(self, left, right):
        return (self.h[right] - self.h[left]*self.p[right-left]) % self.mod

def probably_equal_substrings(s, a, b, length):
    rh = RollingHash(s)
    return rh.get(a,a+length) == rh.get(b,b+length)

正确性思路

  1. 前缀递推等价于字符系数的多项式。
  2. 减去左前缀乘相应幂后只保留 [l,r) 的项。
  3. 相同字符串的系数序列相同,因此哈希必相同。
  4. 逆命题是概率性的;二次参数或原串验证控制碰撞。

复杂度

TimeSpaceParameters
预处理 O(n),每次子串哈希 O(1)O(n)n 为字符串长度;碰撞风险由 base、mod 和哈希组数决定

边界条件

错误模式

PatternWhy it fails / fix
未做幂对齐直接减前缀得到的位置权重不一致。
把哈希相等当数学证明需承认碰撞并验证或双哈希。
参数跨对象不一致不同 base/mod 的值不可比较。

选择与排除规则

相关模板

RelationTemplateBoundary
alternativeTrie 前缀树批量固定长度子串相等而非前缀导航。

原创微型例子

环节内容
Result两段哈希相同,对应 cab。
Scenario字符串 cabcab 比较 [0,3) 与 [3,6)。
Walkthrough第二段通过减去前三字符前缀并乘幂对齐,得到与第一段同一系数序列。

Recall prompts

我的补充