哈希学习笔记
哈希学习笔记
一.哈希函数
是什么
哈希函数就是把一个东西变换成一个值。
二.哈希值
就是哈希函数得到的那个值
三.哈希冲突
是什么
两个不一样的数据具有同样的哈希值。
解决方法
链表
我们来举一个例子,假如我们有\(n\)个数\({a_1,a_2,a_3,...,a_n}\)这是我们可以建立一堆链表,如果有哈希冲突了,就在对应的哈希值的链表后加入一个节点,如图
这样我们就可以解决了(伪代码)
void hash_func(int x) {........;}
vector<int> hashTable[MAXP];
bool insert_hashtable(int x) { // have number before
int hsk = hash_func(x);
for(int i = 0; i < g[hsk].size(); i ++) {
if(g[hsk][i] == x) return true;
}
hashTable[hsk].push_back(x);
return false;
}
完整代码
#include<bits/stdc++.h>
using namespace std;
/*
输入n个整数,求不同的数有多少个
*/
const int mod = 999983;
vector<int> link[1000005];
int Hash(int x) {
return x % mod;
}
bool insert(int x) {
int val = Hash(x);
for(int i = 0; i < link[val].size(); i++)
{
if(link[val][i] == x)
return true;
}
link[val].push_back(x);
return false;
}
int main() {
int n, ans = 0;
cin >> n;
for(int i = 1; i <= n; i++) {
int x;
cin >> x;
if(insert(x) == true)
continue;
ans++;
}
cout << ans;
return 0;
}
四.字符串哈希
是什么
把一个字符串转换成一个整数
怎么做
1.1 进制大法
去一个进制\(base\),这个哈希值\(hashkey=kashkey+base \times str_i\),如果这个数太大,我们就对它取模,这样就好了。
- 一个小技巧,我们可以避免取模运算,使用一个较大的\(base\),然后用\(unsigned \space long \space long\)直接计算,只要最后取模就好了。
1.2 解决效率问题
之前的方法的时间复杂度是\(O(n)\)的,太慢啦!!!
怎么解决呢???
1.3 字符串哈希的性质1
打个比方,你有两个字符串,分别是\(abcd,abcde\),我们可以\(O(1)\)时间出理出\(abcde\)的哈希值,只要我们知道\(abcd\)的哈希值
总的来说\(hash_i=hash_{i-1} \times base + s_i\)
1.4字符串哈希的性质2
对于字符串\(S\)的一个字串\([L,R]\),有\(hash_{L\space to \space R}=hash_R-hash_{L-1} \times base^{R-L+1}\)
懒得证明......
1.5哈希常用质数
9191891,6893911,5170427,3877817,2908361
1.6双哈希
双哈希是什么呢?我们加入要匹配两个字符串,但是单哈希又会被卡,我们可以引入两个模数,对这个字符串哈希两次,我们比较的时候多比一下就好了。
//咕咕咕
制作不易,点个赞在走吧(QAQ)