简单介绍一下字符串hash

相信大家对于hash都不陌生

翻译过来就是搞砸,乱搞的意思嘛

 

hash算法广泛应用于计算机的各类领域,像什么md5,文件效验,磁力链接 等等都会用到hash算法

在信息学奥赛中,hash算法主要应用于搜索状态判重,字符串的比较等

 

hash的主要思想是:对于一个空间、时间需求较大的状态,在一定错误率的基础上进行状态压缩,降低其时间、空间的需求量

对于字符串hash来说,就是把一串字符串压缩成一个hash值,方便我们进行数据的处理

 

接下来我们重点讲一下字符串hash的实现方法

实现方法

思想

在信息学奥赛中,使用最广泛的算法叫做:BKDR Hash

它的核心思想是:

对于一个字符串,选取恰当的进制,将一个字符串看做是一个大整数

(众人:***,你这是要让我们写高精啊)

然后再对一个随便什么数取模就可以啦

 

当然这个“恰当的进制”和“随便什么数”是有讲究的

 

根据砖家的研究:

进制一般选择大于字符串中的最大的字符且不含模数的值因子的数

比如说,如果你是对一串小写字母做字符串hash,那么131这个进制就是不错的选择

 

而“随便什么数”有三种方法

  1. 选择两个模数,判断的时候只有两个hash值都相同才算相同
  2. 选择一个大质数,像11111111111111111111111或者212370440130137957
  3. 用unsigned long long 自然溢出

注意:尽量不要只用一个较小的质数,根据生日悖论,很容易被卡

 

代码

代码实现比较简单

https://www.luogu.org/problemnew/show/3370

  • unsigned long long 自然溢出
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<map>
 8 #define lli long long int 
 9 using namespace std;
10 const int MAXN=100001;
11 int seed=27;
12 void read(int &n)
13 {
14     char c='+';int x=0;bool flag=0;
15     while(c<'0'||c>'9'){c=getchar();if(c=='-')flag=1;}
16     while(c>='0'&&c<='9')x=x*10+c-48,c=getchar();
17     n=flag==1?-x:x;
18 }
19 char a[MAXN];
20 map<long long ,bool>happen;
21 int tot=0;
22 int main()
23 {
24     int n;
25     read(n);
26     for(int i=1;i<=n;i++)
27     {
28         unsigned long long base=1;
29         scanf("%s",a);
30         for(int j=0;j<strlen(a);j++)
31             base=base*seed+(a[j]);
32         if(!happen[base])
33             happen[base]=1,tot++;
34     }
35     printf("%d",tot);
36     return 0;
37 }
ull

相关文章: