Loading

哈希学习笔记

哈希学习笔记

一.哈希函数

是什么

哈希函数就是把一个东西变换成一个值。

二.哈希值

就是哈希函数得到的那个值

三.哈希冲突

是什么

两个不一样的数据具有同样的哈希值。

解决方法

链表

我们来举一个例子,假如我们有\(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双哈希

双哈希是什么呢?我们加入要匹配两个字符串,但是单哈希又会被卡,我们可以引入两个模数,对这个字符串哈希两次,我们比较的时候多比一下就好了。

//咕咕咕
posted @ 2020-11-26 20:25  zhangwenxuan  阅读(150)  评论(0)    收藏  举报