字符串哈希 哈希表

 

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 }
View Code

 


 

 

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 }
View Code

 

posted @ 2019-02-13 17:15  DTTTTTTT  阅读(805)  评论(0编辑  收藏  举报