Hash
求最小冲突质数
探究P本质
对于偶数,%6结果只能为0,2,4(w[]利用率低),而对于%5则为1,2,3,4,5
所以当p为质数时最大有效
for(int i = 100000; ; ++ i)
{
bool flag = true;
for(int j = 2; j * j <= i; ++ j)
if(i % j == 0) {
flag = false;
break;
}
if(flag) {
cout << i << endl;
break;
}
这里引入问题:

brute1(时间上)

思路:用数据结构(1/2/3) + 排序二分
1.map维护表nlogn
2.用trie树:线性,只有13位可以很高效的解决问题
3.手写平衡树来维护信息
取模:进行取模操作(最朴素的hash方案)

但若同余则会发生碰撞
Hash
hash函数:将大值域压缩到小值域
Hash冲突:原值不相同,取模后的值相同的情况叫为“xoi:哈希碰撞”。
5%2333333 <=> 2333338%2333333,发生冲突
解决碰撞: 将模数P增大,P越大碰撞概率越稀疏
假设P = 2,则每两个数都有一半概率碰撞,P = 100w,则每两个数碰撞的概率只有1/100W

- 取双模数:只有两个取模数都指向这个值时,我们认为它存在
双模数降低碰撞,两模数都取质数保证:a*b范围内都是有效的
(一般只有在字符串hash时才写双模hash)
相当于两个检验器,当且仅当两个检验器都为1,才为1
但依然可能会发生碰撞,双模数降低了碰撞,但碰撞还具有存在性
探究P本质
对于偶数,%6结果只能为0,2,4(w[]利用率低),而对于%5则为1,2,3,4,5
所以当p为质数时最大有效
解决Hash冲突的几种方法:

拉链法:拉链存%p的all余数,查找时遍历这个链
点击查看代码
#include <cstdio>
#include <vector>
using namespace std;
#define mod 233333//定义模数
struct zip {
vector<int> w[mod + 5];
void ins(int x) {
w[x % mod].push_back(x);//此时即将x加入到其hash值x%mod序列的结尾
}
void ask(int x) {
//查询时扫一遍vector
for(auto i = w[x % mod].begin(); i != w[x % mod].end(); ++ i)
if(*i == x)//如果恰好等于我们要查询的x
goto done;
puts("No");
return ;
done :
puts("Yes");
}
};
zip B;
int main(void) {
B.ask(5);
B.ins(5);
B.ask(5);
B.ask(5 + mod);
B.ins(5 + mod);
B.ask(5 + mod);
}
STL大法:unordered_set好处是任意类型,O(1)查询,内部实现是一个拉链法
点击查看代码
#include <cstdio>
#include <vector>
#include <unordered_set>
using namespace std;
#define mod 233333//定义模数
unordered_set<int> S;
int main(void) {
printf("%d\n", S.count(5));
S.insert(5);
printf("%d\n", S.count(5));//返回有几个5,一般返回5是否在其中
}
unorder_set可能不支持结构体,但set支持结构体,set的底层实现是一棵红黑树(平衡树一种),unordered_set底层实现为hash
set是有序表,所以可以开结构体类型(前提为结构体定义了小于号)
一般hash可以用set,也可以用unordered_set
线性探测法:蹲坑法?即位置x已有,则看x+1,x+2····直到找到一个为空的位置
平方探测法:若x有东西,则看x2%p是否有东西,看x3%p是否有东西····依次
浙公网安备 33010602011771号