1.字符串哈希
方法概述:
- 选取两个合适的互质常数b,h(b<h),把字符串看成b进制数,算出这个数模h
- 设H(C,k)为前k个字符构成的字符串的哈希值,则:H(C',k)=H(C,k+n)-H(C,k)*bn
--------具体见《信息学奥赛一本通提高篇》
关于正确性:可以用双哈希降低出现相同哈希值的概率 取109+7和109+9,就几乎不可能发生冲突,因为它们是孪生质数
板子题: poj3461
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #define R register
5 #define go(i,a,b) for(R int i=a;i<=b;i++)
6 #define il inline
7 #define ll unsigned long long//记得是unsigned long long
8 #define M 1000001
9 using namespace std;
10 il int rd()
11 {
12 int x=0,y=1;char c=getchar();
13 while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
14 while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
15 return x*y;
16 }
17 int T,l1,l2,ans,b=29;
18 char s1[M],s2[M],tmp[M];
19 ll dat,hash[M],p[M];
20 int main()
21 {
22 T=rd();
23 p[0]=1;go(i,1,1000000) p[i]=p[i-1]*b;
24 while(T--)
25 {
26 scanf("%s%s",s1+1,s2+1);ans=0;
27 l1=strlen(s1+1);l2=strlen(s2+1);
28 hash[0]=1;
29 go(i,1,l2) hash[i]=hash[i-1]*b+(ll)(s2[i]-'A'+1);
30 dat=0;
31 go(i,1,l1) dat=dat*b+(ll)(s1[i]-'A'+1);
32 go(i,0,l2-l1)
33 if(dat==hash[i+l1]-hash[i]*p[l1])ans++;
34 printf("%d\n",ans);
35 }
36 return 0;
37 }
2.哈希表
哈希函数的构造:
- 除余法
- 乘积取整法:用key乘以一个在(0,1)中的实数,得到一个实数,取其小数部分乘以哈希表的大小再向下取整。(最好是无理数,(√5-1/2是一个实际效果很好的数) //我想我大概永远不会用这种方法吧qwq
- 基数转换法:把key值看成另一种进制的数,然后转换成十进制,再用除余法取余
板子题: loj10034 图书管理
1 #include<iostream>
2 #include<cstdio>
3 #include<string>
4 #include<cstring>
5 #define R register
6 #define ll unsigned long long
7 #define go(i,a,b) for(R int i=a;i<=b;i++)
8 #define M 1000010
9 using namespace std;
10 int rd()
11 {
12 int x=0,y=1;char c=getchar();
13 while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
14 while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
15 return x*y;
16 }
17 ll h1=29,h2=73,mod1=1e6+3,mod2=1e6+9,sm1,sm2,b[M];
18 int n,len,ct,l;
19 char tp[10],s[201];
20 struct node{ll w,nt;}a[M];
21 void insert() {a[++ct].nt=b[sm1];a[ct].w=sm2;b[sm1]=ct;}
22 bool find()
23 {
24 for(R int i=b[sm1];i;i=a[i].nt)
25 if(a[i].w==sm2) return 1;
26 return 0;
27 }
28 int main()
29 {
30 n=rd();
31 while(n--)
32 {
33 cin>>tp;gets(s);len=strlen(s)-1;
34 //用cin来读入tp(type)读到空格时就会停止 gets读完一整行(包括换行)
35 sm1=0;sm2=0;
36 cout<<tp<<endl;
37 go(i,0,len) sm1=(sm1*h1+s[i])%mod1,sm2=(sm2*h2+s[i])%mod2;//双哈希
38 if(tp[0]=='a') insert();
39 else if(find()) printf("yes\n");
40 else printf("no\n");
41 }
42 return 0;
43 }
来源:oschina
链接:https://my.oschina.net/u/4333042/blog/3651280