zoukankan      html  css  js  c++  java
  • 字符串哈希 哈希表

    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
    光伴随的阴影
  • 相关阅读:
    10. Regular Expression Matching
    9. Palindrome Number (考虑负数的情况)
    8. String to Integer (整数的溢出)
    7. Reverse Integer (整数的溢出)
    LeetCode Minimum Size Subarray Sum
    LeetCode Course Schedule II
    Linux 文件缓存 (一)
    LeetCode Tries Prefix Tree
    Linux : lsof 命令
    LeetCode Binary Tree Right Side View
  • 原文地址:https://www.cnblogs.com/forward777/p/10370790.html
Copyright © 2011-2022 走看看