字符串hash补充(模数情况下)
字符串模板,在模数意义下的,比较好用
1 #include<stdio.h> 2 typedef long long LL; 3 /*【字符串哈希算法】 4 字符串哈希算法的提出,涉及到如何快速地求两个字符串是否完全相同。 5 如果是查询多个匹配串与某个模板串的相同性关系,我们可以用KMP实现。 6 而如果这些匹配串都是某个串的子串呢?从效率上和思维复杂度上讲,都不如用字符串哈希来实现! 7 什么是字符串哈希呢?比如,我们要哈希一个全为小写字符的串,串长最大为TOP。 8 1,我们决定取模数Z 9 2,我们决定字符集哈希数V 10 3,我们预处理V的幂值:v[0]=1;for(int i=1;i<=TOP;i++)v[i]=v[i-1]*V%Z; 11 4,我们求出模板串s的哈希值: 12 scanf("%s",s); 13 w=0;for(int i=1;s[i];i++)w=(w*V+s[i]-'a')%Z; 14 5,我们求出匹配串ss以任一位置为结尾的前缀哈希值: 15 scanf("%s",ss); 16 u[0]=0;for(int i=1;ss[i];i++)u[i]=(u[i-1]*V+ss[i]-'a')%Z; 17 6,当判定ss[l,r]是否与模板串s相同时,我们求得s[l,r]在同规则下的哈希值ww: 18 把前缀u[l-1]乘上v[r-(l-1)]的base,用u[r]-u[l-1]*v[r-(l-1)],就得到了纯后缀哈希值,也就是s[l,r]的哈希值。 19 即ww=(u[r]-u[l-1]*v[r-(l-1)]%Z+Z)%Z. 20 这时判定w与ww是否相同,就可以判匹配串是否与模板串相同啦。 21 需要事项1: 22 如果哈希值不同,那么两个串必定不同。 23 而就算哈希值相同,两个串依然存在可能性不同。 24 为了提高稳定性,我们可以取多个pair(取模数Z,字符集哈希数V)。利用两次哈希甚至是多次哈希,提高准确性。 25 注意事项2: 26 字符集的不同,我们对应可能采取ch-'a',ch-'A',ch-'0',ch这样各种各样的形式提高哈希的准确的*/ 27 28 const int TOP=1e5,N=TOP+10; 29 const int Z=1e9+7;//取模数 30 const int V=26;//字符集哈希数 31 char s[N],ss[N]; 32 LL v[N];/[x]=V^x%Z 33 LL u[N];//u[x]=hashvalue(1,x); 34 LL hashvalue(int l,int r) 35 { 36 return (u[r]-u[l-1]*v[r-(l-1)]%Z+Z)%Z; 37 } 38 int main() 39 { 40 v[0]=1;for(int i=1;i<=TOP;i++)v[i]=v[i-1]*V%Z; 41 scanf("%s",s+1); 42 LL w=0;for(int i=1;s[i];i++)w=(w*V+s[i]-'a')%Z; 43 scanf("%s",ss+1); 44 u[0]=0;for(int i=1;ss[i];i++)u[i]=(u[i-1]*V+ss[i]-'a')%Z; 45 while(1) 46 { 47 int l,r;scanf("%d%d",&l,&r); 48 LL ww=hashvalue(l,r); 49 printf("ss[%d,%d]%ss\n",l,r,ww==w?"==":"!="); 50 } 51 return 0; 52 }