Tommy Chen home

Hash

6 Oct 2025

1.Introduction

2.Principle

For a string, convert it into a number. If two numbers differ, their original strings differ; if the numbers are equal, the original strings are very likely the same.

A common choice is to interpret a string as a base-131 or base-13331 number and take it modulo M. M is usually a large prime such as 1e9+537. Choosing prime values for both the base and M greatly reduces the chance of a collision.

3.Implementation

The following iterative process converts a string into a base-131 number.

long long Hash(const string& s) {
	const long long base = 131;
	const long long M = 1000000537LL;
	long long res = 0;
	for(char c : s) {
		res = (res * base) + c;
		res %= M;
	}
	return res;
}

Repeatedly comparing complete strings this way is expensive, and obtaining a substring hash is inconvenient. Instead, maintain a prefix array h, where h[i] is the hash of the first i characters (s[1…i]), and a power array g, where g[i] stores base to the i-th power modulo M. The power array is used to calculate substring hashes.

Preprocess as follows in O(n) time.

for(int i = 1; i <= n; i++) {
		h[i] = (1LL * h[i-1] * base + s[i]) % M;
		g[i] = 1LL * g[i-1] * base % M;
}

The hash of the substring from index l to r can then be obtained in O(1).

auto get = [&](int l, int r) -> int {
		return (h[r] - 1LL * h[l-1] * g[r - l + 1] % M + M) % M;
};

String indices start at 0 while the arrays above start at 1. To make indexing convenient, prepend a blank character:

s = " " + s;

4.Example

Example 1: Luogu P10468

Given a string and q queries, each query provides ranges for two substrings of the original string and asks whether they are equal.

This is a standard application of the technique: use the functions above directly.

Total visits to this site: times