Strings
Hash
template < int N >
struct PolyHashing {
i64 s[N];
i64 mod[2] = {1610612741ll, 805306457ll};
i64 pw[N][2];
i64 w[N][2];
void init (int m) {
pw[0][0] = pw[0][1] = 1;
for (int i = 1;i <= m; ++ i) {
pw[i][0] = pw[i - 1][0] * 233ll % mod[0];
pw[i][1] = pw[i - 1][1] * 233ll % mod[1];
}
w[0][0] = w[0][1] = 0;
for (int i = 1;i <= m; ++ i) {
i64 Z = (i64) s[i];
w[i][0] = (w[i - 1][0] * 233ll + Z) % mod[0];
w[i][1] = (w[i - 1][1] * 233ll + Z) % mod[1];
}
return ;
}
i64 query (int l, int r, int v) {return (w[r][v] + mod[v] - (w[l - 1][v] * pw[r - l + 1][v] % mod[v])) % mod[v];}
std :: pair < i64, i64 > val (int l, int r) {return std :: make_pair (query (l, r, 0), query (l, r, 1));}
};
SA
template < int N, int M >
struct SA {
int str[N], n;
bool empty () {return (n == 0);}
int size () {return n;}
void clear () {n = 0; return ;}
void pushchar (int ch) {
str[++ n] = ch;
return ;
}
void popchar () {
assert (!empty ());
n --;
return ;
}
int st[N][M], lg[N];
int rk[N << 1], sa[N], tmp[N << 1], height[N];
void init () {
if (n == 1) {
rk[1] = sa[1] = 1;
height[1] = 0;
lg[0] = -1, lg[1] = 0;
st[1][0] = height[1];
return ;
}
for (int i = 1;i <= n; ++ i) rk[i] = str[i], sa[i] = i;
for (int w = 1; w < n; w <<= 1) {
auto f = [&] (int x) -> std :: pair < int, int > {
return std :: make_pair (rk[x], rk[x + w]);
};
auto g = [&] (int x, int y) -> bool {
return f (x) < f (y);
};
std :: sort (sa + 1, sa + 1 + n, g);
int p = 1;
tmp[sa[1]] = 1;
for (int i = 2;i <= n; ++ i) {
p += (f (sa[i]) != f (sa[i - 1]));
tmp[sa[i]] = p;
}
for (int i = 1;i <= n; ++ i) rk[i] = tmp[i];
}
for (int i = 1, p = 0;i <= n; ++ i) {
if (p > 0) p --;
while (str[i + p] == str[sa[rk[i] - 1] + p]) p ++;
height[rk[i]] = p;
}
for (int i = 1;i <= n; ++ i) st[i][0] = height[i];
for (int j = 1;j < M; ++ j) {
for (int i = 1;i + (1 << j) - 1 <= n; ++ i) {
st[i][j] = std :: min (st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
}
}
lg[0] = -1;
for (int i = 1;i <= n; ++ i) lg[i] = lg[i >> 1] + 1;
return ;
}
int LCPsuf (int x, int y) {
if (x == y) return n - x + 1;
x = rk[x], y = rk[y];
if (x > y) std :: swap (x, y);
x ++;
int k = lg[y - x + 1];
return std :: min (st[x][k], st[y - (1 << k) + 1][k]);
}
int LCP (int l, int r, int x, int y) {
return std :: min ({LCPsuf (l, x), r - l + 1, y - x + 1});
}
};