Open addressing
Insert: Find the position where a number is placed through the find function. If it is not empty, check the next position until an empty position is found or the number already exists.
Search: If the number exists in the hash table, the index of the number will eventually be returned, otherwise the returned index will be empty.
#include <iostream>
#include <cstring>
using namespace std;
/*
为减少hash冲突,取模的数N应为质数
设null的值为1061109567,该数每一位都为0x3f,可用memset初始化
*/
const int N = 200003, null = 0x3f3f3f3f;
int h[N], n;
int find (int x)
{
int k = (x%N + N) % N;
while (h[k] != null && h[k] != x)
{
k++;
if(k == N) k = 0;
}
return k;
}
int main()
{
memset(h, 0x3f, sizeof(h));
cin >> n;
while (n--)
{
char op[2];
int x;
cin >> op >> x;
if (op[0] == 'I') h[find(x)] = x; // 插入操作
else //查找操作
if (h[find(x)] == null) cout << "No" << endl;
else cout << "Yes" << endl;
}
return 0;
}
Zipper method
Idea: Put the data with the same value after hashing in the same linked list, and you only need to traverse the linked list when searching.
Insert: Get the pointer to the head node of the linked list through hash, and then insert the data by head interpolation.
#include <iostream>
#include <cstring>
using namespace std;
const int N = 100003;
int h[N], e[N], ne[N], idx; //h中存放第一个节点的索引, e存放数据域,ne存放指针域, idx代表当前使用到了第几个节点
void add(int x) // 等同于头插法
{
int k = (x % N + N) % N;
e[idx] = x;
ne[idx] = h[k];
h[k] = idx++;
}
bool find(int x)
{
int k = (x % N + N) % N;
for (int i = h[k]; i != -1; i = ne[i]) // 末节点的指针指向-1,代表链表遍历完毕
if(e[i] == x) return true;
return false;
}
int main()
{
memset(h, -1, sizeof(h)); // 将所有值置为-1,代表各链表均为空
int n;
cin >> n;
while (n--)
{
char op[2];
int x;
cin >> op >> x;
if (op[0] == 'I') add(x); // 插入操作
else //查找操作
if(find(x)) cout << "Yes" << endl;
else cout << "No" << endl;
}
return 0;
}
String prefix hashing
Idea: Think of a string as a number, and each character in the string represents one bit.
#include <iostream>
using namespace std;
typedef unsigned long long ULL; // 将hash值定为无符号长整形, 让其自动溢出, 相当于% 2^64
const int N = 100010, Q = 13331; // 为避免hash冲突, 将进制设置为131或13331
int h[N], q[N];
ULL get(int l, int r) // 获取截取子串哈希值
{
return h[r] - h[l-1] * q[r-l+1];
}
int main()
{
int n, m;
char str[N];
cin >> n >> m;
scanf("%s", str + 1);
q[0] = 1;
for (int i = 1; i <= n; i++) // 初始化,q[i]的值为Q^(i-1),h[i]为前i个字符所组成子串的哈希值
{
q[i] = q[i-1] * Q;
h[i] = h[i-1] * Q + str[i];
}
int l1, r1, l2, r2;
for (int i = 0; i < m; i++)
{
cin >> l1 >> r1 >> l2 >> r2;
if(get(l1, r1) == get(l2, r2)) cout << "Yes" << endl;
else cout << "No" << endl;
}
return 0;
}