This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub Luzhiled/syakyo-library
#include "src/string/rolling-hash.hpp"
#pragma once #include <algorithm> #include <cstdint> #include <vector> namespace luz { struct RollingHash { using u64 = std::uint64_t; using u128 = __uint128_t; static const u64 mod = (1ull << 61ull) - 1; const u64 base; std::vector< u64 > power; static inline u64 add(u64 a, u64 b) { if((a += b) >= mod) a -= mod; return a; } static inline u64 mul(u64 a, u64 b) { u128 c = u128(a) * b; return add(c >> 61, c & mod); } inline void expand(int sz) { int pre_sz = power.size(); if(pre_sz < sz + 1) { power.resize(sz + 1); for(int i = pre_sz - 1; i < sz; i++) { power[i + 1] = mul(power[i], base); } } } RollingHash() : base(mod - 5), power{1} {} template< class Iter > std::vector< u64 > build(Iter f, Iter l) const { std::vector< u64 > hs(1); hs.reserve(l - f + 1); while (f != l) { u64 h = add(mul(hs.back(), base), *f); hs.emplace_back(h); ++f; } return hs; } u64 query(const std::vector< u64 > &s, int l, int r) { expand(r - l); return add(s[r], mod - mul(s[l], power[r - l])); } u64 combine(u64 h1, u64 h2, size_t h2len) { expand(h2len); return add(mul(h1, power[h2len]), h2); } int lcp(const std::vector< u64 > &a, int l1, int r1, const std::vector< u64 > &b, int l2, int r2) { int len = std::min(r1 - l1, r2 - l2); int low = 0, high = len + 1; while (high - low > 1) { int mid = (low + high) / 2; if (query(a, l1, l1 + mid) == query(b, l2, l2 + mid)) low = mid; else high = mid; } return low; } }; }
#line 2 "src/string/rolling-hash.hpp" #include <algorithm> #include <cstdint> #include <vector> namespace luz { struct RollingHash { using u64 = std::uint64_t; using u128 = __uint128_t; static const u64 mod = (1ull << 61ull) - 1; const u64 base; std::vector< u64 > power; static inline u64 add(u64 a, u64 b) { if((a += b) >= mod) a -= mod; return a; } static inline u64 mul(u64 a, u64 b) { u128 c = u128(a) * b; return add(c >> 61, c & mod); } inline void expand(int sz) { int pre_sz = power.size(); if(pre_sz < sz + 1) { power.resize(sz + 1); for(int i = pre_sz - 1; i < sz; i++) { power[i + 1] = mul(power[i], base); } } } RollingHash() : base(mod - 5), power{1} {} template< class Iter > std::vector< u64 > build(Iter f, Iter l) const { std::vector< u64 > hs(1); hs.reserve(l - f + 1); while (f != l) { u64 h = add(mul(hs.back(), base), *f); hs.emplace_back(h); ++f; } return hs; } u64 query(const std::vector< u64 > &s, int l, int r) { expand(r - l); return add(s[r], mod - mul(s[l], power[r - l])); } u64 combine(u64 h1, u64 h2, size_t h2len) { expand(h2len); return add(mul(h1, power[h2len]), h2); } int lcp(const std::vector< u64 > &a, int l1, int r1, const std::vector< u64 > &b, int l2, int r2) { int len = std::min(r1 - l1, r2 - l2); int low = 0, high = len + 1; while (high - low > 1) { int mid = (low + high) / 2; if (query(a, l1, l1 + mid) == query(b, l2, l2 + mid)) low = mid; else high = mid; } return low; } }; }