• 字符串哈希 哈希表


    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
    ",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
    ");
    40         else printf("no
    ");
    41     }
    42     return 0;
    43 }
    View Code
    光伴随的阴影
  • 相关阅读:
    P4315 月下“毛景树”
    P1505 [国家集训队]旅游
    P3258 [JLOI2014]松鼠的新家
    P4116 Qtree3
    P2580 于是他错误的点名开始了
    P3038 [USACO11DEC]牧草种植Grass Planting
    P3128 [USACO15DEC]最大流Max Flow
    P2146 [NOI2015]软件包管理器
    P2590 [ZJOI2008]树的统计
    P3384 【模板】树链剖分
  • 原文地址:https://www.cnblogs.com/forward777/p/10370790.html
Copyright © 2020-2023  润新知