zoukankan      html  css  js  c++  java
  • 字符串hash&&对字符串hash的理解

     对字符串hash的一些总结:

    1,首先,我们在转化的时候,取底的时候一般是取131这些数,因为要避免不同的字符串对应相同的hash值这种情况的出现。如果卡精度的时候,我们可以采取双模数的方式尽量减少误差,(不过这种东西还是得看脸)。

    2,在定义的时候,一般是为了定义成unsigned long long ,这个有一个好处,当爆int的时候,不会带上负号,就相当于对2的64次方进行取模了。

    3.在进行hash的转换的时候,字符串对应的0位,hash值不是0,所以我们可以先将字符串往后移动一位再去赋值。

    4,我们将一个整的字符串计算好hash值的时候,如果要取(l,r)这段区间的子串的hash值,可以采用以下公式。

    ans =  hash[r] - hash[l-1]*ind[r-l+1];

    A

    单模数hash

    题目链接:https://www.luogu.org/problemnew/show/P3370

    具体思路:我们可以将字符串的每一个字符转换成数字,然后比较的时候,直接比较这个字符串对应的hash值就可以了。

    AC代码:

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<iomanip>
     4 #include<stack>
     5 #include<algorithm>
     6 #include<string>
     7 #include<cstring>
     8 #include<cmath>
     9 using namespace std;
    10 # define ll long long
    11 # define ull unsigned long long
    12 const int base=131;//一般比ascii码值大就可以了。
    13 const int maxn = 1e4+100;
    14 char str[maxn];
    15 ll a[maxn];
    16 ull Hash(char a[])
    17 {
    18     int len=strlen(a);
    19     ull sum=0;
    20     for(int i=0; i<len; i++)
    21     {
    22         sum=sum*base+(ull)a[i];
    23     }
    24     return sum;
    25 }
    26 int main()
    27 {
    28     int n;
    29     scanf("%d",&n);
    30     for(int i=1; i<=n; i++)
    31     {
    32         scanf("%s",str);
    33         a[i]=Hash(str);
    34     }
    35     sort(a+1,a+n+1);
    36     int ans=1;
    37     for(int i=2; i<=n; i++)
    38     {
    39         if(a[i]!=a[i-1])
    40             ans++;
    41     }
    42     printf("%d
    ",ans);
    43     return 0;
    44 }

    双模数hash

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<iomanip>
     4 #include<stack>
     5 #include<algorithm>
     6 #include<string>
     7 #include<cstring>
     8 #include<cmath>
     9 using namespace std;
    10 # define ll long long
    11 # define ull unsigned long long
    12 const int mod1=1e9+7;
    13 const int mod2=1e9+9;
    14 const int base=131;
    15 const int maxn = 1e4+100;
    16 char str[maxn];
    17 struct node{
    18 ull t1;
    19 ull t2;
    20 }q[maxn];
    21 bool cmp(node s1,node s2){
    22 return s1.t1<s2.t1;
    23 }
    24 ull hash1(char *a){
    25 ull sum=0;
    26 int len=strlen(a);
    27 for(int i=0;i<len;i++){
    28 sum=(sum*base+(ull)a[i])%mod1;
    29 }
    30 return sum;
    31 }
    32 ull hash2(char *a){
    33 ull sum=0;
    34 int len=strlen(a);
    35 for(int i=0;i<len;i++){
    36 sum=(sum*base+(ull)a[i])%mod2;
    37 }
    38 return sum;
    39 }
    40 int main()
    41 {
    42     int n;
    43     scanf("%d",&n);
    44     for(int i=1; i<=n; i++)
    45     {
    46         scanf("%s",str);
    47        q[i].t1=hash1(str);
    48         q[i].t2=hash2(str);
    49     }
    50     sort(q+1,q+n+1,cmp);
    51     int ans=1;
    52     for(int i=2;i<=n;i++){
    53     if(q[i].t1!=q[i-1].t1||q[i].t2!=q[i-1].t2)ans++;
    54     }
    55     printf("%d
    ",ans);
    56     return 0;
    57 }

    B题:

    题目链接:https://cn.vjudge.net/contest/276379#problem/J

    题目大意:这本来是一道kmp的模板题,然后今下午打算用字符串hash做一下,结果一下午过去了,,,,

     具体思路:和拓展kmp的方法相同,就是比较的时候直接比较子串的hash值就可以了。

    AC代码:

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<iomanip>
     4 #include<stack>
     5 #include<algorithm>
     6 #include<map>
     7 #include<string>
     8 #include<cstring>
     9 #include<cmath>
    10 using namespace std;
    11 # define ll long long
    12 # define ull unsigned long long
    13 const int mod1=1e9+7;
    14 const int mod2=1e9+9;
    15 const ull base=131;
    16 const int maxn = 1e5+100;
    17 char str1[maxn],str2[maxn],com[30];
    18 ull hash1[maxn],hash2[maxn],ind[maxn];
    19 map<char,char>vis;
    20 void init()
    21 {
    22     ind[0]=1;
    23     for(int i=1; i<maxn; i++)
    24     {
    25         ind[i]=ind[i-1]*base;
    26     }
    27 }
    28 void hs1(char *a)
    29 {
    30     int len=strlen(a+1);
    31     hash1[0]=0;
    32     for(int i=1; i<=len; i++)
    33     {
    34         hash1[i]=hash1[i-1]*base+(ull)a[i];
    35     }
    36 }
    37 void hs2(char *a)
    38 {
    39     int len=strlen(a+1);
    40     hash2[0]=0;
    41     for(int i=1; i<=len; i++)
    42     {
    43         hash2[i]=hash2[i-1]*base+(ull)a[i];
    44     }
    45 }
    46 ull getsub1(int l,int r)
    47 {
    48     return hash1[r]-hash1[l-1]*ind[r-l+1];
    49 }
    50 ull getsub2(int l,int r)
    51 {
    52     return hash2[r]-hash2[l-1]*ind[r-l+1];
    53 }
    54 int main()
    55 {
    56     init();
    57     int T;
    58     scanf("%d",&T);
    59     while(T--)
    60     {
    61         scanf("%s",com);
    62         scanf("%s",str1+1);
    63         for(int i=0; i<26; i++)
    64         {
    65             vis[com[i]]=char('a'+i);
    66         }
    67         int len=strlen(str1+1);
    68         for(int i=1; i<=len; i++)
    69         {
    70             str2[i]=vis[str1[i]];
    71         }
    72         hs1(str1);
    73         hs2(str2);
    74         int ans=len;
    75         for(int i=len; i<len+len; i++)
    76         {
    77             if(i&1)continue;
    78             int tmp=i/2;
    79             ull t1=getsub2(1,len-tmp);
    80             ull t2=getsub1(len-(len-tmp)+1,len);
    81             if(t1==t2)
    82             {
    83                 ans=tmp;
    84                 break;
    85             }
    86         }
    87         for(int i=1; i<=ans; i++)
    88         {
    89             printf("%c",str1[i]);
    90         }
    91         for(int i=1; i<=ans; i++)
    92         {
    93             printf("%c",str2[i]);
    94         }
    95         printf("
    ");
    96     }
    97     return 0;
    98 }
    99  
  • 相关阅读:
    Java修炼之道--I/O
    配置tomcat资源文件软连接
    配置tomcat按天输出日志文件
    Ubuntu 安装rabbitmq
    Ubuntu下 JDK、tomcat、redis离线安装
    Nginx+tomcat负载均衡环境搭建
    Tomcat性能调优及性能测试工具配置
    Tomcat搭建https并与APR模式兼容
    IDEA开发工具小技巧整理
    Ubuntu下Nginx+fastDFS环境安装
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10262748.html
Copyright © 2011-2022 走看看