Skip to content

Instantly share code, notes, and snippets.

@kungfulon
Created June 5, 2020 20:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kungfulon/9a917b23699196450d18ed8f94d7773d to your computer and use it in GitHub Desktop.
Save kungfulon/9a917b23699196450d18ed8f94d7773d to your computer and use it in GitHub Desktop.
Simple rolling hash
class Hash {
public:
Hash(const std::string &s) : hash1(s.size() + 1), hash2(s.size() + 1) {
if (base == -1) {
base = genBase(minBase, mod);
pow1.push_back(1);
pow2.push_back(1);
}
while (pow1.size() <= s.size()) {
pow1.push_back(1ll * pow1.back() * base % mod);
pow2.push_back(pow2.back() * base);
}
for (int i = 0; i < s.size(); ++i) {
hash1[i + 1] = (1ll * hash1[i] * base + s[i]) % mod;
hash2[i + 1] = hash2[i] * base + s[i];
}
}
pair<int, unsigned long> get(int pos, int len) {
if (pos < 0 || len < 0 || pos + len >= hash1.size()) {
throw std::out_of_range("out of range");
}
int h1 = (hash1[pos + len] - (1ll * hash1[pos] * pow1[len]) % mod) % mod;
if (h1 < 0) h1 += mod;
unsigned long h2 = hash2[pos + len] - hash2[pos] * pow2[len];
return {h1, h2};
}
private:
int genBase(int lo, int hi) {
auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
std::mt19937 mt_rand(seed);
int base = std::uniform_int_distribution<int>(lo + 1, hi)(mt_rand);
return base % 2 == 0 ? base-1 : base;
}
static constexpr int minBase = 256;
static constexpr int mod = 1000000007;
static vector<int> pow1;
static vector<unsigned long> pow2;
static int base;
vector<int> hash1;
vector<unsigned long> hash2;
};
vector<int> Hash::pow1;
vector<unsigned long> Hash::pow2;
int Hash::base = -1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment