就像cantor映射一样,字符串hash采取一种更加随机化的映射,它的通项公式为$hash[i]=\sum _{j=0}^{i}s[j]*p^{i-j}$,如此将一个字符串随机映射到了一个数字上,
我们来看这个公式的意义,他把一个字符串映射到了一个p进制数字上,位数代表着字符串的长度,然后我们将这个p进制数转化为十进制数并对1e9+7取模来存储,通项公式不好求,但是我们可以通过递推公式来求
$hash[i]=hash[i-1]\cdot p+s[i]$
这个公式就比较友好了,另外对于任意区间,我们有这个公式
$hash[l~r] = hash[r] - hash[l - 1] \cdot pow(p, r - l + 1)$
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 
 | struct str_hash {static const int maxn = 3e5 + 5, p = 47, mod = 1e9 + 7;
 static int pw[maxn], pr[maxn];
 int h1[maxn], h2[maxn], len;
 
 str_hash() {
 if (pw[0] == 1) return;
 pw[0] = pr[0] = 1;
 int rev = qpow(p, mod - 2, mod);
 for (int i = 1; i < maxn; i++) {
 pw[i] = 1ll * pw[i - 1] * p % mod;
 pr[i] = 1ll * pr[i - 1] * rev % mod;
 }
 }
 
 void extend(char c) {
 len++;
 h1[len] = (1ll * h1[len - 1] * p + c) % mod;
 h2[len] = (h2[len - 1] + 1ll * c * pw[len - 1]) % mod;
 }
 
 void ini() { len = 0; }
 
 int query(int l, int r) { return (h1[r] + 1ll * h1[l - 1] * (mod - pw[r - l + 1])) % mod; }
 int qurev(int l, int r) { return 1ll * (h2[r] - h2[l - 1] + mod) * pr[l - 1] % mod; }
 };
 
 int str_hash::pw[maxn], str_hash::pr[maxn];
 
 
 
 typedef unsigned long long ull;
 
 struct double_hash {
 static const ull maxn = 1e3 + 666, p = 26, mod1 = 1e9 + 7, mod2 = 1e9 + 9;
 static ull pw1[maxn], pw2[maxn];
 ull hash1[maxn], hash2[maxn], len;
 
 double_hash() {
 if (pw1[0] == 1)return;
 pw1[0] = pw2[0] = 1;
 for (ull i = 1; i < maxn; i++) {
 pw1[i] = pw1[i - 1] * p % mod1;
 pw2[i] = pw2[i - 1] * p % mod2;
 }
 }
 
 void build(char *s, ull _len) {
 len = _len;
 for (ull i = 1; i <= len; i++) {
 hash1[i] = (hash1[i - 1] * p + s[i] - 'a') % mod1;
 hash2[i] = (hash2[i - 1] * p + s[i] - 'a') % mod2;
 }
 }
 
 ull query1(ull l, ull r) { return (hash1[r] - hash1[l - 1] * pw1[r - l + 1] % mod1 + mod1) % mod1; }
 
 ull query2(ull l, ull r) { return (hash2[r] - hash2[l - 1] * pw2[r - l + 1] % mod2 + mod2) % mod2; }
 
 ull query(ull l, ull r) { return query1(l, r) * mod2 + query2(l, r); }
 } hash_a, hash_b;
 
 ull double_hash::pw1[maxn], double_hash::pw2[maxn];
 
 | 
http://codeforces.com/contest/727/problem/E 
给你一个长度为n×k的环,环上每一个位置有一个字符。现在给你g个长度为k的字符串,问是否可以在g个字符串中选出n个构成这个环。
   1 ≤ n ≤ 10^5, 1 ≤ k ≤ 10^5, n*k ≤ 10^6, n ≤ g ≤ 10^5, g*k ≤ 2*10^6
枚举起点,hash.