This documentation is automatically generated by online-judge-tools/verification-helper
#ifndef _LIB_ROLLING_HASH
#define _LIB_ROLLING_HASH
#include "ModularInteger.cpp"
#include "Random.cpp"
#include "Traits.cpp"
#include <bits/stdc++.h>
namespace lib {
using namespace std;
namespace hashing {
namespace {
using traits::HasBidirectionalIterator;
using traits::HasInputIterator;
using traits::IsBidirectionalIterator;
using traits::IsInputIterator;
using traits::IsRandomIterator;
} // namespace
const static int DEFAULT_MAX_POWERS = 1e6 + 5;
const static int GOOD_MOD1 = (int)1e9 + 7;
const static int GOOD_MOD2 = (int)1e9 + 9;
template <typename T, T... Mods> struct BaseProvider {
typedef BaseProvider<T, Mods...> type;
typedef ModularInteger<T, Mods...> mint_type;
mint_type b;
vector<mint_type> powers;
int max_powers = 0;
BaseProvider(T bases[sizeof...(Mods)]) : powers(1, 1) {
b = mint_type::with_remainders(bases);
}
BaseProvider() : powers(1, 1) {
T bases[sizeof...(Mods)];
for (size_t i = 0; i < sizeof...(Mods); i++)
bases[i] = rng::gen.uniform_int(mint_type::mods[i]);
b = mint_type::with_remainders(bases);
}
void set_max_powers(int x) { max_powers = x; }
inline operator mint_type() const { return b; }
inline T operator()(int i) { return b[i]; }
void ensure(int p) const {
type *self = const_cast<type *>(this);
int cur = powers.size();
if (p > cur)
self->powers.resize(max(2 * cur, p));
else
return;
int nsz = powers.size();
for (int i = cur; i < nsz; i++)
self->powers[i] = powers[i - 1] * b;
}
mint_type power(int p) const {
if (p >= max_powers)
return b ^ p;
ensure(p + 1);
return powers[p];
}
T power(int p, int i) const { return power(p)[i]; }
};
template <typename T, T... Mods> struct RollingHash {
typedef RollingHash<T, Mods...> type;
typedef ModularInteger<T, Mods...> mint_type;
typedef BaseProvider<T, Mods...> base_type;
vector<mint_type> hs;
struct Hash {
mint_type x;
int n;
struct Less {
typename mint_type::less mint_less;
bool operator()(const Hash &lhs, const Hash &rhs) const {
if (lhs.n == rhs.n)
return mint_less(lhs.x, rhs.x);
return lhs.n < rhs.n;
}
};
typedef Less less;
Hash() : n(0) {}
explicit Hash(mint_type y) : x(y), n(1) {}
Hash(mint_type y, int n) : x(y), n(n) { assert(n >= 0); }
explicit operator mint_type() const { return x; }
friend bool operator==(const Hash &lhs, const Hash &rhs) {
return tie(lhs.n, lhs.x) == tie(rhs.n, rhs.x);
}
friend bool operator!=(const Hash &lhs, const Hash &rhs) {
return !(lhs == rhs);
}
friend ostream &operator<<(ostream &output, const Hash &var) {
return output << var.x << "{" << var.n << "}";
}
};
struct Cat {
shared_ptr<base_type> base;
Cat(const shared_ptr<base_type> &base) : base(base) {}
template <
typename Iterator,
typename enable_if<IsInputIterator<Iterator>::value>::type * = nullptr>
Hash operator()(Iterator begin, Iterator end) {
Hash res;
for (auto it = begin; it != end; ++it) {
res.n += it->n;
res.x *= base->power(it->n);
res.x += it->x;
}
return res;
}
Hash operator()(const initializer_list<Hash> &hashes) {
return (*this)(hashes.begin(), hashes.end());
}
template <class... Args> Hash operator()(Args... args) {
return (*this)({args...});
}
template <class... Args>
pair<Hash, Hash> cat(const pair<Args, Args> &... args) {
initializer_list<Hash> fwd_list = {args.first...};
initializer_list<Hash> bwd_list = {args.second...};
return {cat(fwd_list.begin(), fwd_list.end()),
cat(bwd_list.rbegin(), bwd_list.rend())};
}
};
Cat cat;
RollingHash(const shared_ptr<base_type> &base) : hs(1), cat(base) {}
template <
typename Container,
typename enable_if<HasInputIterator<Container>::value>::type * = nullptr>
RollingHash(const Container &container, const shared_ptr<base_type> &base)
: hs(1), cat(base) {
(*this) += container;
}
template <
typename Iterator,
typename enable_if<IsInputIterator<Iterator>::value>::type * = nullptr>
RollingHash(Iterator begin, Iterator end, const shared_ptr<base_type> &base)
: hs(1), cat(base) {
append(begin, end);
}
inline int size() const { return (int)hs.size() - 1; }
template <
typename Iterator,
typename enable_if<IsRandomIterator<Iterator>::value>::type * = nullptr>
void append(Iterator begin, Iterator end) {
int i = hs.size();
hs.resize(hs.size() + distance(begin, end));
for (auto it = begin; it != end; ++it, ++i)
hs[i] = hs[i - 1] * (*cat.base) + mint_type(*it);
}
template <
typename Iterator,
typename enable_if<!IsRandomIterator<Iterator>::value>::type * = nullptr>
void append(Iterator begin, Iterator end) {
for (auto it = begin; it != end; ++it)
(*this) += *it;
}
template <typename U> void append(U rhs) { (*this) += rhs; }
template <typename U,
typename enable_if<is_integral<U>::value>::type * = nullptr>
RollingHash &operator+=(U rhs) {
hs.push_back(mint_type(rhs) + hs.back() * (*cat.base));
return *this;
}
template <
typename Container,
typename enable_if<HasInputIterator<Container>::value>::type * = nullptr>
RollingHash &operator+=(const Container &rhs) {
append(rhs.begin(), rhs.end());
return *this;
}
inline void pop() {
assert(size() > 0);
hs.pop_back();
}
Hash prefix(int n) const {
n = min(n, size());
return Hash(hs[n], n);
}
Hash operator()(int i, int j) const {
return Hash(hs[j + 1] - hs[i] * (cat.base->power(j - i + 1)), j - i + 1);
}
Hash suffix(int n) const {
int sz = size();
n = min(n, sz);
return (*this)(sz - n, sz - 1);
}
pair<Hash, Hash> border(int n) const { return {prefix(n), suffix(n)}; }
Hash substr(int i) const {
i = min(i, size());
return (*this)(i, size() - 1);
}
Hash substr(int i, int j) const { return (*this)(i, j); }
Hash all() const { return Hash(hs.back(), size()); }
friend int lcp(const type &lhs, const type &rhs) {
int l = 0, r = min(lhs.size(), rhs.size());
while (l < r) {
int mid = (l + r) / 2;
if (lhs.hs[mid + 1] != rhs.hs[mid + 1])
r = mid;
else
l = mid + 1;
}
return l;
}
friend bool operator<(const type &lhs, const type &rhs) {
int l = lcp(lhs, rhs);
if (l == min(lhs.size(), rhs.size()))
return lhs.size() < rhs.size();
return lhs(l, l) < rhs(l, l);
}
};
template <typename T, T... Mods> struct BidirectionalRollingHash {
typedef RollingHash<T, Mods...> type;
using Hash = typename type::Hash;
using base_type = typename type::base_type;
using Cat = typename type::Cat;
type fwd, bwd;
typename type::Cat cat;
template <typename Container,
typename enable_if<HasBidirectionalIterator<Container>::value>::type
* = nullptr>
BidirectionalRollingHash(const Container &container,
const shared_ptr<base_type> &base)
: BidirectionalRollingHash<T, Mods...>(container.begin(), container.end(),
base) {}
template <typename Iterator,
typename enable_if<IsBidirectionalIterator<Iterator>::value>::type
* = nullptr>
BidirectionalRollingHash(Iterator begin, Iterator end,
const shared_ptr<base_type> &base)
: fwd(begin, end, base),
bwd(make_reverse_iterator(end), make_reverse_iterator(begin), base),
cat(base) {}
inline Hash forward(int i, int j) const { return fwd(i, j); }
inline Hash backward(int i, int j) const {
int n = fwd.size();
return bwd(n - j - 1, n - i - 1);
}
inline pair<Hash, Hash> operator()(int i, int j) const {
return {forward(i, j), backward(i, j)};
}
};
template <typename R> struct HashProvider {
typedef R Roll;
typedef typename R::base_type base_type;
typedef typename R::Hash Hash;
typename R::Cat cat;
HashProvider() : cat(make_shared<base_type>()) {}
explicit HashProvider(base_type base) : cat(make_shared<base_type>(base)) {}
template <class... Args> R operator()(Args... args) {
return R(args..., cat.base);
}
};
template <typename R> struct PowerHashProvider : HashProvider<R> {
using typename HashProvider<R>::base_type;
using HashProvider<R>::cat;
PowerHashProvider() : PowerHashProvider<R>(base_type()) {}
PowerHashProvider(base_type base) : HashProvider<R>(base) {
cat.base->set_max_powers(DEFAULT_MAX_POWERS);
}
};
template <int32_t... Mods> using Roll32 = RollingHash<int32_t, Mods...>;
template <int64_t... Mods> using Roll64 = RollingHash<int64_t, Mods...>;
template <int32_t... Mods>
using Biroll32 = BidirectionalRollingHash<int32_t, Mods...>;
template <int64_t... Mods>
using Biroll64 = BidirectionalRollingHash<int64_t, Mods...>;
using DefaultProvider = PowerHashProvider<Roll32<GOOD_MOD1, GOOD_MOD2>>;
using BiDefaultProvider = PowerHashProvider<Biroll32<GOOD_MOD1, GOOD_MOD2>>;
} // namespace hashing
} // namespace lib
#endif
#line 1 "RollingHash.cpp"
#line 1 "ModularInteger.cpp"
#line 1 "NumberTheory.cpp"
#include <bits/stdc++.h>
namespace lib {
using namespace std;
namespace nt {
int64_t inverse(int64_t a, int64_t b) {
long long b0 = b, t, q;
long long x0 = 0, x1 = 1;
if (b == 1)
return 1;
while (a > 1) {
q = a / b;
t = b, b = a % b, a = t;
t = x0, x0 = x1 - q * x0, x1 = t;
}
if (x1 < 0)
x1 += b0;
return x1;
}
template<typename T, typename U>
T powmod (T a, U b, U p) {
int res = 1;
while (b)
if (b & 1)
res = (int) (res * 1ll * a % p), --b;
else
a = (int) (a * 1ll * a % p), b >>= 1;
return res;
}
template<typename T>
vector<T> factors(T n) {
vector<T> f;
for(T i = 2; i*i <= n; i++) {
if(n % i == 0) f.push_back(i);
while(n % i == 0) n /= i;
}
if(n > 1) f.push_back(n);
return f;
}
} // namespace nt
} // namespace lib
#line 5 "ModularInteger.cpp"
#if __cplusplus < 201300
#error required(c++14)
#endif
namespace lib {
using namespace std;
namespace {
template <typename T, T... Mods> struct ModularIntegerBase {
typedef ModularIntegerBase<T, Mods...> type;
T x[sizeof...(Mods)];
friend ostream &operator<<(ostream &output, const type &var) {
output << "(";
for (int i = 0; i < sizeof...(Mods); i++) {
if (i)
output << ", ";
output << var.x[i];
}
return output << ")";
}
};
template <typename T, T Mod> struct ModularIntegerBase<T, Mod> {
typedef ModularIntegerBase<T, Mod> type;
constexpr static T mod = Mod;
T x[1];
T& data() { return this->x[0]; }
T data() const { return this->x[0]; }
explicit operator int() const { return this->x[0]; }
explicit operator int64_t() const { return this->x[0]; }
explicit operator double() const { return this->x[0]; }
explicit operator long double() const { return this->x[0]; }
friend ostream &operator<<(ostream &output, const type &var) {
return output << var.x[0];
}
};
template<typename T, typename U, T... Mods>
struct InversesTable {
constexpr static size_t n_mods = sizeof...(Mods);
constexpr static T mods[sizeof...(Mods)] = {Mods...};
constexpr static int n_inverses = 1e6 + 10;
T v[n_inverses][n_mods];
T max_x;
InversesTable() : v(), max_x(n_inverses) {
for(int j = 0; j < sizeof...(Mods); j++)
v[1][j] = 1, max_x = min(max_x, mods[j]);
for(int i = 2; i < max_x; i++) {
for(int j = 0; j < sizeof...(Mods); j++) {
v[i][j] = mods[j] - (T)((U)(mods[j] / i) * v[mods[j] % i][j] % mods[j]);
}
}
}
};
// Make available for linkage.
template <typename T, class U, T... Mods>
constexpr T InversesTable<T, U, Mods...>::mods[];
template <typename T, class Enable, T... Mods>
struct ModularIntegerImpl : ModularIntegerBase<T, Mods...> {
typedef ModularIntegerImpl<T, Enable, Mods...> type;
typedef T type_int;
typedef uint64_t large_int;
constexpr static size_t n_mods = sizeof...(Mods);
constexpr static T mods[sizeof...(Mods)] = {Mods...};
using ModularIntegerBase<T, Mods...>::x;
using Inverses = InversesTable<T, large_int, Mods...>;
struct Less {
bool operator()(const type &lhs, const type &rhs) const {
for (size_t i = 0; i < sizeof...(Mods); i++)
if (lhs.x[i] != rhs.x[i])
return lhs.x[i] < rhs.x[i];
return false;
};
};
typedef Less less;
constexpr ModularIntegerImpl() {
for (size_t i = 0; i < sizeof...(Mods); i++)
x[i] = T();
}
constexpr ModularIntegerImpl(large_int y) {
for (size_t i = 0; i < sizeof...(Mods); i++) {
x[i] = y % mods[i];
if (x[i] < 0)
x[i] += mods[i];
}
}
static type with_remainders(T y[sizeof...(Mods)]) {
type res;
for (size_t i = 0; i < sizeof...(Mods); i++)
res.x[i] = y[i];
res.normalize();
return res;
}
inline void normalize() {
for (size_t i = 0; i < sizeof...(Mods); i++)
if ((x[i] %= mods[i]) < 0)
x[i] += mods[i];
}
inline T operator[](int i) const { return x[i]; }
inline T multiply(T a, T b, T mod) const { return (large_int)a * b % mod; }
inline T inv(T a, T mod) const { return static_cast<T>(nt::inverse(a, mod)); }
inline T invi(T a, int i) const {
const static Inverses inverses = Inverses();
if(a < inverses.max_x)
return inverses.v[a][i];
return inv(a, mods[i]);
}
type inverse() const {
T res[sizeof...(Mods)];
for (size_t i = 0; i < sizeof...(Mods); i++)
res[i] = invi(x[i], i);
return type::with_remainders(res);
}
template <typename U> T power_(T a, U p, T mod) {
if (mod == 1)
return T();
if (p < 0) {
if (a == 0)
throw domain_error("0^p with negative p is invalid");
p = -p;
a = inv(a, mod);
}
if (p == 0)
return T(1);
if (p == 1)
return a;
T res = 1;
while (p > 0) {
if (p & 1)
res = multiply(res, a, mod);
p >>= 1;
a = multiply(a, a, mod);
}
return res;
}
inline type &operator+=(const type &rhs) {
for (size_t i = 0; i < sizeof...(Mods); i++)
if ((x[i] += rhs.x[i]) >= mods[i])
x[i] -= mods[i];
return *this;
}
inline type &operator-=(const type &rhs) {
for (size_t i = 0; i < sizeof...(Mods); i++)
if ((x[i] -= rhs.x[i]) < 0)
x[i] += mods[i];
return *this;
}
inline type &operator*=(const type &rhs) {
for (size_t i = 0; i < sizeof...(Mods); i++)
x[i] = multiply(x[i], rhs.x[i], mods[i]);
return *this;
}
inline type &operator/=(const type &rhs) {
for (size_t i = 0; i < sizeof...(Mods); i++)
x[i] = multiply(x[i], invi(rhs.x[i], i), mods[i]);
return *this;
}
inline type &operator+=(T rhs) {
for (size_t i = 0; i < sizeof...(Mods); i++)
if ((x[i] += rhs) >= mods[i])
x[i] -= mods[i];
return *this;
}
type &operator-=(T rhs) {
for (size_t i = 0; i < sizeof...(Mods); i++)
if ((x[i] -= rhs) < 0)
x[i] += mods[i];
return *this;
}
type &operator*=(T rhs) {
for (size_t i = 0; i < sizeof...(Mods); i++)
x[i] = multiply(x[i], rhs, mods[i]);
return *this;
}
type &operator/=(T rhs) {
for (size_t i = 0; i < sizeof...(Mods); i++)
x[i] = multiply(invi(rhs, i), x[i], mods[i]);
return *this;
}
type &operator^=(large_int p) {
for (size_t i = 0; i < sizeof...(Mods); i++)
x[i] = power_(x[i], p, mods[i]);
return *this;
}
type &operator++() {
for (size_t i = 0; i < sizeof...(Mods); i++)
if ((++x[i]) >= mods[i])
x[i] -= mods[i];
return *this;
}
type &operator--() {
for (size_t i = 0; i < sizeof...(Mods); i++)
if ((--x[i]) < 0)
x[i] += mods[i];
return *this;
}
type operator++(int unused) {
type res = *this;
++(*this);
return res;
}
type operator--(int unused) {
type res = *this;
--(*this);
return res;
}
friend type operator+(const type &lhs, const type &rhs) {
type res = lhs;
return res += rhs;
}
friend type operator-(const type &lhs, const type &rhs) {
type res = lhs;
return res -= rhs;
}
friend type operator*(const type &lhs, const type &rhs) {
type res = lhs;
return res *= rhs;
}
friend type operator/(const type &lhs, const type &rhs) {
type res = lhs;
return res /= rhs;
}
friend type operator+(const type &lhs, T rhs) {
type res = lhs;
return res += rhs;
}
friend type operator-(const type &lhs, T rhs) {
type res = lhs;
return res -= rhs;
}
friend type operator*(const type &lhs, T rhs) {
type res = lhs;
return res *= rhs;
}
friend type operator/(const type &lhs, T rhs) {
type res = lhs;
return res /= rhs;
}
friend type operator^(const type &lhs, large_int rhs) {
type res = lhs;
return res ^= rhs;
}
friend type power(const type &lhs, large_int rhs) { return lhs ^ rhs; }
type operator-() const {
type res = *this;
for (size_t i = 0; i < sizeof...(Mods); i++)
if (res.x[i])
res.x[i] = mods[i] - res.x[i];
return res;
}
friend bool operator==(const type &lhs, const type &rhs) {
for (size_t i = 0; i < sizeof...(Mods); i++)
if (lhs.x[i] != rhs.x[i])
return false;
return true;
}
friend bool operator!=(const type &lhs, const type &rhs) {
return !(lhs == rhs);
}
friend istream &operator>>(istream &input, type &var) {
T y;
cin >> y;
var = y;
return input;
}
};
} // namespace
// Explicitly make constexpr available for linkage.
template <typename T, class Enable, T... Mods>
constexpr T ModularIntegerImpl<T, Enable, Mods...>::mods[];
template <typename T, T... Mods>
using ModularInteger =
ModularIntegerImpl<T, typename enable_if<is_integral<T>::value>::type,
Mods...>;
template <int32_t... Mods> using Mint32 = ModularInteger<int32_t, Mods...>;
template <int64_t... Mods> using Mint64 = ModularInteger<int64_t, Mods...>;
using MintP = Mint32<(int32_t)1e9+7>;
using MintNTT = Mint32<998244353>;
} // namespace lib
#line 1 "Random.cpp"
#line 4 "Random.cpp"
namespace lib {
using namespace std;
namespace rng {
struct Generator {
mt19937 rng;
Generator() {
seed_seq seq {
(uint64_t) chrono::duration_cast<chrono::nanoseconds>(
chrono::high_resolution_clock::now().time_since_epoch())
.count(),
#if __cplusplus > 201300
(uint64_t)make_unique<char>().get(),
#else
(uint64_t)unique_ptr<char>(new char).get(),
#endif
(uint64_t)__builtin_ia32_rdtsc()
};
rng = mt19937(seq);
}
Generator(seed_seq &seq) : rng(seq) {}
template <typename T,
typename enable_if<is_integral<T>::value>::type * = nullptr>
inline T uniform_int(T L, T R) {
return uniform_int_distribution<T>(L, R)(rng);
}
template <typename T> inline T uniform_int(T N) {
return uniform_int(T(), N - 1);
}
template <typename T> inline T uniform_real(T N) {
return uniform_real(0.0, static_cast<double>(N));
}
template <typename T> inline T uniform_real(T L, T R) {
return uniform_real_distribution<double>(static_cast<double>(L),
static_cast<double>(R))(rng);
}
inline double uniform_real() { return uniform_real(0.0, 1.0); }
};
static Generator gen = Generator();
} // namespace rng
static rng::Generator &rng_gen = rng::gen;
} // namespace lib
#line 1 "Traits.cpp"
#line 4 "Traits.cpp"
namespace lib {
using namespace std;
namespace traits {
template <typename...> struct make_void { using type = void; };
template <typename... T> using void_t = typename make_void<T...>::type;
/// keep caide
template <typename Iterator>
using IteratorCategory = typename iterator_traits<Iterator>::iterator_category;
/// keep caide
template <typename Container>
using IteratorCategoryOf = IteratorCategory<typename Container::iterator>;
/// keep caide
template <typename Iterator>
using IteratorValue = typename iterator_traits<Iterator>::value_type;
/// keep caide
template <typename Container>
using IteratorValueOf = IteratorValue<typename Container::iterator>;
/// keep caide
template <typename Iterator>
using IsRandomIterator =
is_base_of<random_access_iterator_tag, IteratorCategory<Iterator>>;
/// keep caide
template <typename Iterator>
using IsInputIterator =
is_base_of<input_iterator_tag, IteratorCategory<Iterator>>;
/// keep caide
template <typename Iterator>
using IsBidirectionalIterator =
is_base_of<bidirectional_iterator_tag, IteratorCategory<Iterator>>;
/// keep caide
template <typename Container>
using HasRandomIterator =
is_base_of<random_access_iterator_tag, IteratorCategoryOf<Container>>;
/// keep caide
template <typename Container>
using HasInputIterator =
is_base_of<input_iterator_tag, IteratorCategoryOf<Container>>;
/// keep caide
template <typename Container>
using HasBidirectionalIterator =
is_base_of<bidirectional_iterator_tag, IteratorCategoryOf<Container>>;
} // namespace traits
} // namespace lib
#line 7 "RollingHash.cpp"
namespace lib {
using namespace std;
namespace hashing {
namespace {
using traits::HasBidirectionalIterator;
using traits::HasInputIterator;
using traits::IsBidirectionalIterator;
using traits::IsInputIterator;
using traits::IsRandomIterator;
} // namespace
const static int DEFAULT_MAX_POWERS = 1e6 + 5;
const static int GOOD_MOD1 = (int)1e9 + 7;
const static int GOOD_MOD2 = (int)1e9 + 9;
template <typename T, T... Mods> struct BaseProvider {
typedef BaseProvider<T, Mods...> type;
typedef ModularInteger<T, Mods...> mint_type;
mint_type b;
vector<mint_type> powers;
int max_powers = 0;
BaseProvider(T bases[sizeof...(Mods)]) : powers(1, 1) {
b = mint_type::with_remainders(bases);
}
BaseProvider() : powers(1, 1) {
T bases[sizeof...(Mods)];
for (size_t i = 0; i < sizeof...(Mods); i++)
bases[i] = rng::gen.uniform_int(mint_type::mods[i]);
b = mint_type::with_remainders(bases);
}
void set_max_powers(int x) { max_powers = x; }
inline operator mint_type() const { return b; }
inline T operator()(int i) { return b[i]; }
void ensure(int p) const {
type *self = const_cast<type *>(this);
int cur = powers.size();
if (p > cur)
self->powers.resize(max(2 * cur, p));
else
return;
int nsz = powers.size();
for (int i = cur; i < nsz; i++)
self->powers[i] = powers[i - 1] * b;
}
mint_type power(int p) const {
if (p >= max_powers)
return b ^ p;
ensure(p + 1);
return powers[p];
}
T power(int p, int i) const { return power(p)[i]; }
};
template <typename T, T... Mods> struct RollingHash {
typedef RollingHash<T, Mods...> type;
typedef ModularInteger<T, Mods...> mint_type;
typedef BaseProvider<T, Mods...> base_type;
vector<mint_type> hs;
struct Hash {
mint_type x;
int n;
struct Less {
typename mint_type::less mint_less;
bool operator()(const Hash &lhs, const Hash &rhs) const {
if (lhs.n == rhs.n)
return mint_less(lhs.x, rhs.x);
return lhs.n < rhs.n;
}
};
typedef Less less;
Hash() : n(0) {}
explicit Hash(mint_type y) : x(y), n(1) {}
Hash(mint_type y, int n) : x(y), n(n) { assert(n >= 0); }
explicit operator mint_type() const { return x; }
friend bool operator==(const Hash &lhs, const Hash &rhs) {
return tie(lhs.n, lhs.x) == tie(rhs.n, rhs.x);
}
friend bool operator!=(const Hash &lhs, const Hash &rhs) {
return !(lhs == rhs);
}
friend ostream &operator<<(ostream &output, const Hash &var) {
return output << var.x << "{" << var.n << "}";
}
};
struct Cat {
shared_ptr<base_type> base;
Cat(const shared_ptr<base_type> &base) : base(base) {}
template <
typename Iterator,
typename enable_if<IsInputIterator<Iterator>::value>::type * = nullptr>
Hash operator()(Iterator begin, Iterator end) {
Hash res;
for (auto it = begin; it != end; ++it) {
res.n += it->n;
res.x *= base->power(it->n);
res.x += it->x;
}
return res;
}
Hash operator()(const initializer_list<Hash> &hashes) {
return (*this)(hashes.begin(), hashes.end());
}
template <class... Args> Hash operator()(Args... args) {
return (*this)({args...});
}
template <class... Args>
pair<Hash, Hash> cat(const pair<Args, Args> &... args) {
initializer_list<Hash> fwd_list = {args.first...};
initializer_list<Hash> bwd_list = {args.second...};
return {cat(fwd_list.begin(), fwd_list.end()),
cat(bwd_list.rbegin(), bwd_list.rend())};
}
};
Cat cat;
RollingHash(const shared_ptr<base_type> &base) : hs(1), cat(base) {}
template <
typename Container,
typename enable_if<HasInputIterator<Container>::value>::type * = nullptr>
RollingHash(const Container &container, const shared_ptr<base_type> &base)
: hs(1), cat(base) {
(*this) += container;
}
template <
typename Iterator,
typename enable_if<IsInputIterator<Iterator>::value>::type * = nullptr>
RollingHash(Iterator begin, Iterator end, const shared_ptr<base_type> &base)
: hs(1), cat(base) {
append(begin, end);
}
inline int size() const { return (int)hs.size() - 1; }
template <
typename Iterator,
typename enable_if<IsRandomIterator<Iterator>::value>::type * = nullptr>
void append(Iterator begin, Iterator end) {
int i = hs.size();
hs.resize(hs.size() + distance(begin, end));
for (auto it = begin; it != end; ++it, ++i)
hs[i] = hs[i - 1] * (*cat.base) + mint_type(*it);
}
template <
typename Iterator,
typename enable_if<!IsRandomIterator<Iterator>::value>::type * = nullptr>
void append(Iterator begin, Iterator end) {
for (auto it = begin; it != end; ++it)
(*this) += *it;
}
template <typename U> void append(U rhs) { (*this) += rhs; }
template <typename U,
typename enable_if<is_integral<U>::value>::type * = nullptr>
RollingHash &operator+=(U rhs) {
hs.push_back(mint_type(rhs) + hs.back() * (*cat.base));
return *this;
}
template <
typename Container,
typename enable_if<HasInputIterator<Container>::value>::type * = nullptr>
RollingHash &operator+=(const Container &rhs) {
append(rhs.begin(), rhs.end());
return *this;
}
inline void pop() {
assert(size() > 0);
hs.pop_back();
}
Hash prefix(int n) const {
n = min(n, size());
return Hash(hs[n], n);
}
Hash operator()(int i, int j) const {
return Hash(hs[j + 1] - hs[i] * (cat.base->power(j - i + 1)), j - i + 1);
}
Hash suffix(int n) const {
int sz = size();
n = min(n, sz);
return (*this)(sz - n, sz - 1);
}
pair<Hash, Hash> border(int n) const { return {prefix(n), suffix(n)}; }
Hash substr(int i) const {
i = min(i, size());
return (*this)(i, size() - 1);
}
Hash substr(int i, int j) const { return (*this)(i, j); }
Hash all() const { return Hash(hs.back(), size()); }
friend int lcp(const type &lhs, const type &rhs) {
int l = 0, r = min(lhs.size(), rhs.size());
while (l < r) {
int mid = (l + r) / 2;
if (lhs.hs[mid + 1] != rhs.hs[mid + 1])
r = mid;
else
l = mid + 1;
}
return l;
}
friend bool operator<(const type &lhs, const type &rhs) {
int l = lcp(lhs, rhs);
if (l == min(lhs.size(), rhs.size()))
return lhs.size() < rhs.size();
return lhs(l, l) < rhs(l, l);
}
};
template <typename T, T... Mods> struct BidirectionalRollingHash {
typedef RollingHash<T, Mods...> type;
using Hash = typename type::Hash;
using base_type = typename type::base_type;
using Cat = typename type::Cat;
type fwd, bwd;
typename type::Cat cat;
template <typename Container,
typename enable_if<HasBidirectionalIterator<Container>::value>::type
* = nullptr>
BidirectionalRollingHash(const Container &container,
const shared_ptr<base_type> &base)
: BidirectionalRollingHash<T, Mods...>(container.begin(), container.end(),
base) {}
template <typename Iterator,
typename enable_if<IsBidirectionalIterator<Iterator>::value>::type
* = nullptr>
BidirectionalRollingHash(Iterator begin, Iterator end,
const shared_ptr<base_type> &base)
: fwd(begin, end, base),
bwd(make_reverse_iterator(end), make_reverse_iterator(begin), base),
cat(base) {}
inline Hash forward(int i, int j) const { return fwd(i, j); }
inline Hash backward(int i, int j) const {
int n = fwd.size();
return bwd(n - j - 1, n - i - 1);
}
inline pair<Hash, Hash> operator()(int i, int j) const {
return {forward(i, j), backward(i, j)};
}
};
template <typename R> struct HashProvider {
typedef R Roll;
typedef typename R::base_type base_type;
typedef typename R::Hash Hash;
typename R::Cat cat;
HashProvider() : cat(make_shared<base_type>()) {}
explicit HashProvider(base_type base) : cat(make_shared<base_type>(base)) {}
template <class... Args> R operator()(Args... args) {
return R(args..., cat.base);
}
};
template <typename R> struct PowerHashProvider : HashProvider<R> {
using typename HashProvider<R>::base_type;
using HashProvider<R>::cat;
PowerHashProvider() : PowerHashProvider<R>(base_type()) {}
PowerHashProvider(base_type base) : HashProvider<R>(base) {
cat.base->set_max_powers(DEFAULT_MAX_POWERS);
}
};
template <int32_t... Mods> using Roll32 = RollingHash<int32_t, Mods...>;
template <int64_t... Mods> using Roll64 = RollingHash<int64_t, Mods...>;
template <int32_t... Mods>
using Biroll32 = BidirectionalRollingHash<int32_t, Mods...>;
template <int64_t... Mods>
using Biroll64 = BidirectionalRollingHash<int64_t, Mods...>;
using DefaultProvider = PowerHashProvider<Roll32<GOOD_MOD1, GOOD_MOD2>>;
using BiDefaultProvider = PowerHashProvider<Biroll32<GOOD_MOD1, GOOD_MOD2>>;
} // namespace hashing
} // namespace lib