字符串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\n",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\n",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("\n");
96     }
97     return 0;
98 }
99  

 

posted @ 2019-01-02 18:04  Let_Life_Stop  阅读(986)  评论(0编辑  收藏  举报