进制哈希

进制哈希的作用:把字符赋予进制和模数,将每一个字符串映射为一个小于模数数字。

具体操作:首先设一个进制数base,并设一个模数mod,进制哈希就是把一个串转化为一个值,这个值是base进制的,储存在哈希表中,注意一下在存入的时候取模一下即可。

哈希冲突:什么是哈希冲突:比如 wsy 的哈希值是2333,然而 mxq 的哈希值也是2333,这样就会产生哈希冲突,从而让哈希算法判断失误。

解决办法

  1. 用一个大质数当模数
  2. 双模数哈希:(通过设置两个不同的哈希方式,对于一个字符串,当且仅当两个哈希值都相同时才判定相同。)
  3. 自然溢出法

核心代码

#define base 233317
#define inf 212370440130137957(LL)
ull mod = inf;

ull hasha(char s[]){
    ll ans=0, len=strlen(s);
    for(ll i=0;i<len;i++){
        ans = (ans*base + (ull)s[i])%mod;
        //枚举该字符串的每一位,与base相乘,转化为base进制,加(ull)是为了防止爆栈搞出一个负数,(ull)是无符号的,但其实加了一个ull是可以不用mod的,加个mod更保险
        //然而加了mod会很玄学,莫名比不加mod慢
    }
    return ans;
}

模板题目:P3370 【模板】字符串哈希

 

 

 

 1.自然溢出法 AC_Code:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <cstring>
 5 #include <string>
 6 #include <algorithm>
 7 using namespace std;
 8 typedef long long ll;
 9 typedef unsigned long long ull;
10 const int maxn = 10000+10;
11 const ull base = 233317;
12 const ull mod = 1e9+7;
13 
14 int n;
15 char s[maxn];
16 ull hash_key[maxn];
17 
18 ull get_hash(char s[]){
19     ull ans=0;
20     int len=strlen(s);
21     for(int i=0;i<len;i++){
22         ans = (ans*base + (ull)s[i]);
23         //这里不使用mod让它自然溢出,定义为ull的数在超过2^32的时候会自然溢出(自然溢出看队友的解释,相当于自动对pow(2,64)-1 取模,无需再手动取模)
24         //如果把这个换成上面的hash就会400ms+
25         //所以说自然溢出大法好
26     }
27     return ans;
28 }
29 
30 int main()
31 {
32     scanf("%d",&n);
33     for(int i=1;i<=n;i++){
34         scanf("%s",s);
35         hash_key[i] = get_hash(s);
36     }
37     sort(hash_key+1,hash_key+1+n);
38     int ans=1;
39     for(int i=1;i<n;i++){
40         if( hash_key[i]!=hash_key[i+1] ){
41             ans ++;
42         }
43     }
44     printf("%d\n",ans);
45     return 0;
46 }

2.双哈希AC_Code:(其实就是用两个不同的mod来算hash,哈希冲突的概率是降低了很多,不过常数大,容易被卡,这道题要400ms+)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <cstring>
 5 #include <string>
 6 #include <algorithm>
 7 using namespace std;
 8 typedef long long ll;
 9 typedef unsigned long long ull;
10 
11 const int maxn = 10000+10;
12 const ull base = 233317;
13 const ull mod1 = 1e9+7;
14 const ull mod2 = 212370440130137957;
15 
16 int n;
17 char s[maxn];
18 struct node{
19     ll x,y;
20 }hash_key[maxn];
21 
22 bool cmp1(node a, node b){
23     return a.x < b.x;
24 }
25 bool cmp2(node a, node b){
26     return a.y < b.y;
27 }
28 
29 ull hash1(char s[]){
30     ull ans=0;
31     int len=strlen(s);
32     for(int i=0;i<len;i++){
33         ans = (ans*base + (ull)s[i])%mod1;
34     }
35     return ans;
36 }
37 
38 ull hash2(char s[]){
39     ull ans=0;
40     int len=strlen(s);
41     for(int i=0;i<len;i++){
42         ans = (ans*base + (ull)s[i])%mod2;
43     }
44     return ans;
45 }
46 
47 int main()
48 {
49     scanf("%d",&n);
50     for(int i=1;i<=n;i++){
51         scanf("%s",s);
52         hash_key[i].x = hash1(s);
53         hash_key[i].y = hash2(s);
54     }
55     sort(hash_key+1,hash_key+1+n,cmp1);
56     sort(hash_key+1,hash_key+1+n,cmp2);
57     int ans = 1;
58     for(ll i=1;i<n;i++){
59         if( hash_key[i].x!=hash_key[i+1].x || hash_key[i].y!=hash_key[i+1].y){
60             ans ++;
61         }
62     }
63     printf("%d\n",ans);
64     return 0;
65 }

参考博客:here

posted @ 2020-11-14 20:14  swsyya  阅读(391)  评论(0编辑  收藏  举报

回到顶部