A hash that can be updated in when the window slides by one character — the basis of Rabin-Karp and of most sliding-window string techniques.
The update
For the polynomial hash over a window of length :
long long h = 0, pw = 1;
for (int i = 0; i < k; i++) { h = (h * B + s[i]) % M; if (i) pw = pw * B % M; }
// slide from window [i, i+k) to [i+1, i+k+1)
h = ((h - s[i] * pw % M + M * M) % M * B + s[i + k]) % M;Watch the sign: subtracting before taking the modulus can go negative, so add a multiple of first.
Rolling hash vs prefix hashing
| Rolling hash | Prefix hashing | |
|---|---|---|
| Memory | ||
| Arbitrary substring | ✘ (only the current window) | ✔ |
| Sliding window | ✔ | ✔ |
| Streaming input | ✔ | ✘ |
| Code | shorter | slightly longer |
Prefix hashing is strictly more capable and almost always what you want in a contest. Rolling hash matters for streaming (the text does not fit in memory) and for algorithms where the memory is the point.
Where rolling hashes are the right tool
Rabin-Karp matching
Hash the pattern once, roll a window across the text, verify on a hash match. expected. See Rabin-Karp.
2D pattern matching
Hash each row of the pattern, then roll horizontally across each text row to get a per-position row hash. Now treat each text column of row-hashes as a 1D string and roll vertically. for an text — the standard solution to “find this rectangular pattern in this grid”.
Rabin fingerprinting / content-defined chunking
Split a data stream at positions where the rolling hash has trailing zero bits. Because the boundaries depend on content rather than offset, inserting bytes at the start does not shift every subsequent chunk — which is why rsync, borg and most deduplicating backup systems use exactly this.
Cyclic polynomial (Buzhash)
An alternative rolling hash using rotations and XOR instead of multiplication:
Faster (no multiplication) and with better bit distribution, at the cost of weaker theoretical guarantees.
Collision defence
The same rules as prefix hashing:
- Randomise the base at runtime.
- Use , not and never overflow.
- Verify on match when the number of candidate positions is small — this makes Rabin-Karp deterministic in its output, with only the running time being probabilistic.
- Double hashing if the number of comparisons is large.
Anti-hash tests
A fixed base modulo is broken by the Thue-Morse sequence in length, and any fixed is vulnerable to a precomputed birthday attack. On Codeforces, assume every hashing problem has an anti-hash test. Randomising the base at runtime costs one line and defeats all of them.
Choosing a base
Any value in works, chosen at random. It should exceed the alphabet size so that distinct characters cannot alias, and be coprime to (automatic when is prime).
See also: String Hashing · Rabin-Karp · Polynomial Hashing