/*
使用前先调用 : H.init()
读入 : H.read()
获得 [l, r] 的hash值: H.get(l,r)
(范围是unsigned long long, 要统计请使用map<unsigned long long, int>)
判断两个子串是否相等 : H.equals(l1, r1, l2, r2)
访问字符串第i个元素 : H[i]
*/
const int H_N = 1e6+10;
const int H_P = 131;
int H_len;
struct string_Hash{
char s[H_N];
unsigned long long f[H_N], p[H_N];
void init() {
p[0] = 1;
for (int i = 1; i < H_N; i++) {
p[i] = p[i-1] * H_P;
}
}
void read() {
scanf("%s",s+1);
H_len = strlen(s+1);
p[0] = 1, f[0] = 0;
for (int i = 1; i <= H_len; i++) {
f[i] = f[i-1] * H_P + s[i];
}
}
inline unsigned long long get(int l = 1, int r = H_len) {
return f[r] - f[l-1] * p[r-l+1];
}
bool equals(int l1, int r1, int l2, int r2) {
return get(l1, r1) == get(l2, r2);
}
inline int size() {
return H_len;
}
inline int length() {
return H_len;
}
inline char front() {
return s[1];
}
inline char back() {
return s[H_len];
}
inline char *begin() {
return s+1;
}
inline char *end() {
return s+H_len;
}
inline char *string() {
return s+1;
}
inline void push_back(char ch) {
s[++H_len] = ch;
f[H_len] = f[H_len-1] * H_P + ch;
}
inline void append(char ch) {
s[++H_len] = ch;
f[H_len] = f[H_len-1] * H_P + ch;
}
inline void push_back(char str[]) {
int length = strlen(str);
for (int i = 0; i < length; i++) {
s[++H_len] = str[i];
f[H_len] = f[H_len-1] * H_P + str[i];
}
}
inline void append(char str[]) {
int length = strlen(str);
for (int i = 0; i < length; i++) {
s[++H_len] = str[i];
f[H_len] = f[H_len-1] * H_P + str[i];
}
}
char operator [] (int idx) {
return s[idx];
}
}H;