之前有写过一篇hash表,不过那是非常久远的时候了,应该是大一刚学一个学期的时候的成果,后来也就不那样写了,后来从xiaoxin那里学习了hash的写法,比较容易用也比较方便多hash,就这样。

分别按照下标从0和从1开始写了一遍。

在Hash结构体中

B是基,要求大于出现的数(如对于字符串应该大于127),可用171、191

mod是模数,最好是一个大素数,如1e9+7、1e9+9

Base是预处理出的B的幂,Base[i]表示B的i次幂

Has是前缀Hash数组

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define MP make_pair
 5 #define PB push_back
 6 const int mod = 1e9 + 7;
 7 const double eps = 1e-8;
 8 const int INF = 0x3f3f3f3f;
 9 const int maxn = 1e5 + 5;
10 const int maxm = 1e6 + 5;
11 
12 struct Hash{
13     ll B,mod,len,Has[maxn],Base[maxn];
14 
15     void init(char *s, int _len, ll _B, ll _mod){    // s[0] 开始 
16         B = _B; mod = _mod; len = _len;
17         Base[0] = 1; Has[0] = 0;
18         for(int i=1;i<=len;i++){
19             Base[i] = Base[i-1]*B%mod;
20             Has[i] = (Has[i-1]*B + s[i-1])%mod;
21         }
22     }
23 
24     ll gethash(int l,int r){        // s[l]~s[r] 
25         l++; r++;
26         return ((Has[r] - Has[l-1] * Base[r-l+1] % mod) + mod) % mod;
27     }
28 };
29 
30 struct Hash{
31     ll B,mod,len,Has[maxn],Base[maxn];
32 
33     void init(char *s, int _len, ll _B, ll _mod){    // s[1] 开始 
34         B = _B; mod = _mod; len = _len;
35         Base[0] = 1; Has[0] = 0;
36         for(int i=1;i<=len;i++){
37             Base[i] = Base[i-1]*B%mod;
38             Has[i] = (Has[i-1]*B + s[i])%mod;
39         }
40     }
41 
42     ll gethash(int l,int r){        // s[l]~s[r] 
43         return ((Has[r] - Has[l-1] * Base[r-l+1] % mod) + mod) % mod;
44     }
45 };

 

调用时初始化都为:

Hash H;

H.init(s, len, 171, mod);

这种形式,其中 s 是字符数组名,len是字符串长度,171为自己指定的基,mod是自己指定的大素数。

常见写法也有通过自然溢出来完成取模的,此时就去掉所有的mod操作,将所有 ll 改为 ull 即可。