オープンアドレス法
挿入:検索機能を使用して、番号が配置されている位置を検索します。空でない場合は、空の位置が見つかるか、番号がすでに存在するまで、次の位置を確認します。
検索:番号がハッシュテーブルに存在する場合、番号のインデックスが最終的に返されます。存在しない場合、返されるインデックスは空になります。
#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;
}
ジッパー方式
アイデア:ハッシュ後に同じ値のデータを同じリンクリストに配置し、検索時にリンクリストをトラバースするだけで済みます。
挿入:ハッシュを介してリンクリストのヘッドノードへのポインターを取得し、データを挿入します。ヘッド補間による。
#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;
}
文字列プレフィックスハッシュ
アイデア:文字列を数字と考えてください。文字列の各文字は1ビットを表します。
#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;
}