String hashing is incredibly fast, but standard single-modulo or unsigned long long hashes are easily hacked by malicious test cases. Even standard double hashes can get clunky to write during a fast Div. 2 round. Here is a highly compact, robust, random-seeded 64-bit string hashing template that runs in linear time and uses structural randomization to ensure it cannot be hacked.
The Implementation
#include <bits/stdc++.h>
using namespace std;
// Compact, anti-hack random-seeded 64-bit string hasher
struct SafeHash {
const long long MOD = (1LL << 61) - 1; // 61st Mersenne Prime
long long base;
vector<long long> h, p;
SafeHash(const string& s) {
int n = s.size();
// Generate a secure random base to prevent anti-hash hacking
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
base = uniform_int_distribution<long long>(256, MOD - 1)(rng) | 1;
h.assign(n + 1, 0); p.assign(n + 1, 1);
for (int i = 0; i < n; i++) {
h[i + 1] = (__int128(h[i]) * base + s[i]) % MOD;
p[i + 1] = (__int128(p[i]) * base) % MOD;
}
}
// Returns the 64-bit hash of subarray s[l...r] inclusive
long long get_hash(int l, int r) {
long long res = (h[r + 1] - __int128(h[l]) * p[r - l + 1]) % MOD;
return res < 0 ? res + MOD : res;
}
};
Why this works beautifully:
- Mersenne Prime
2^61 - 1: It provides an enormous state space, completely removing the need for a secondary hash while comfortably fitting within C++'s standard standard__int128types during multiplication. mt19937_64Clock Seed: The base multiplier changes completely every single time you submit. Even if a hacker looks at your code syntax, they cannot predict the runtime values, rendering deliberate collision hacks mathematically impossible.









Hope this random-seeded
SafeHashtemplate saves you from anti-hash hacks during your next contest! Drop a comment if you have any suggestions, improvements, or cool variations.