对字符串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