开放寻址法
插入:通过find函数查找一个数放置的位置,若不为空,则查看下一个位置,直到找到空的位置或查到该数已经存在。
查找:如果hash表中存在该数,则最终会返回该数的索引,否则返回的索引所在位置为空。
#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;
}
拉链法
思路:将hash后得到相同值的数据放在同一条链表中,查找时只需遍历该链表即可
插入:通过哈希取得指向该链表的头节点的指针,然后用头插法插入数据。
#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;
}
字符串前缀哈希法
思路:将字符串当作一个数,字符串中每个字符代表一位。
#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;
}