哈希表
一.模拟散列表:
1 维护一个集合,支持如下几种操作: 2 3 I x,插入一个数 x; 4 Q x,询问数 x 是否在集合中出现过; 5 现在要进行 N 次操作,对于每个询问操作输出对应的结果。 6 7 输入格式 8 第一行包含整数 N,表示操作数量。 9 10 接下来 N 行,每行包含一个操作指令,操作指令为 I x,Q x 中的一种。 11 12 输出格式 13 对于每个询问指令 Q x,输出一个询问结果,如果 x 在集合中出现过,则输出 Yes,否则输出 No。 14 15 每个结果占一行。 16 17 数据范围 18 1≤N≤105 19 ?109≤x≤109 20 输入样例: 21 5 22 I 1 23 I 2 24 I 3 25 Q 2 26 Q 5 27 输出样例: 28 Yes 29 No
这里有两种写法:
(1)开发寻址法(蹲坑法):我们只开一个一维数组,但数组的大小一般要开到N*2--N*3,其思想是:先用哈希函数算出,数存放的大概位置,
遇到冲突,则到下一个位置去看有没有人,若有接着往下看。无,说明找到了。
1 #include
2 #include
3
4 using namespace std;
5
6 const int N = 200003, null = 0x3f3f3f3f;
7
8 int h[N];
9
10 int find(int x)//find函数的作用是找到x应该保存到的地方:
11 {
12 int t = (x % N + N) % N;//哈希函数,其作用是将数x映射到我们较小的集合中,即先算出数x要保存的大概位置
13 while (h[t] != null && h[t] != x)//h[t]!null表示t这个位置有人,且人不是x
14 {
15 t ++ ;
16 if (t == N) t = 0;//这一步很重要:
17 }
18 return t;
19 }
20
21 int main()
22 {
23 memset(h, 0x3f, sizeof h);
24
25 int n;
26 scanf("%d", &n);
27
28 while (n -- )
29 {
30 char op[2];
31 int x;
32 scanf("%s%d", op, &x);
33 if (*op == 'I') h[find(x)] = x;
34 else
35 {
36 if (h[find(x)] == null) puts("No");
37 else puts("Yes");
38 }
39 }
40
41 return 0;
42 }
这里解释一下为什么哈希函数写成:t=(x%N+N)%N;
因为X为-1e9~1e9,而在计算机中,一个负数去取模得到的还是负数,为了保证t不是负数还要加个N,
但如果当x是正数时,x%N+N会大于N,所以还要%N;
还有一种写法是拉链法:
这里直接用y总的:
1 #include
2 #include
3
4 using namespace std;
5
6 const int N = 100003;
7
8 int h[N], e[N], ne[N], idx;
9
10 void insert(int x)
11 {
12 int k = (x % N + N) % N;
13 e[idx] = x;
14 ne[idx] = h[k];
15 h[k] = idx ++ ;
16 }
17
18 bool find(int x)
19 {
20 int k = (x % N + N) % N;
21 for (int i = h[k]; i != -1; i = ne[i])
22 if (e[i] == x)
23 return true;
24
25 return false;
26 }
27
28 int main()
29 {
30 int n;
31 scanf("%d", &n);
32
33 memset(h, -1, sizeof h);
34
35 while (n -- )
36 {
37 char op[2];
38 int x;
39 scanf("%s%d", op, &x);
40
41 if (*op == 'I') insert(x);
42 else
43 {
44 if (find(x)) puts("Yes");
45 else puts("No");
46 }
47 }
48
49 return 0;
50 }
51
52 作者:yxc
53 链接:https://www.acwing.com/activity/content/code/content/45308/
54 来源:AcWing
55 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
二.字符串哈希:
这位大佬的讲的特别好:https://www.acwing.com/solution/content/24738/
要在此基础上补充上几点:
1.p[N]这个数组是用来保存p的次方的:
因为p[N]也是ULL 类型,所以当其爆数值时,相当于自动%2^64;
2.关于哈希值的公式推导:
所以 才有h[l,r]=h[r]-h[l-1]*p[r-l+1]