这个是在学习哈希表的时候偶然带出来的,想着都是hash家的人,一起看看,结果比哈希表难好多【或许是哈希表学的不深入】;
字符串hash主要应用在:寻找长度为n的主串S中的匹配串T(长度为m)出现的位置或次数的问题属于字符串匹配问题。【将KMP一起看了,这种问题用KMP也可以解决啊,而且人家KMP的代码短啊,,也是不太清楚字符串hash存在的意义是啥,,】如果是从主串中每次选出两个子串判断是否匹配问题,还是要用字符串hash求解。
1》将字符串中的每一个字母都看做是一个数字(例:从a-z,视为1-26);
2》选取两个合适的互质常数 b,h ( b < h )【互质,有用;b < h,有用too】;
3》定义哈希函数,H(C)=[ c1*b^(m-1) + c2*b^(m-2) + . . . + c0*b^0 ] mod h
【看不懂吧,看不懂就对了,我也看不懂hhhh~
(1) C代表一个字符串,用C=c1 c2 c3 c4..cm;表示该字符串,其中 ci 表示从前向后数的第 i 个字符;
(2) 方括号[ ]内的表达式:c1*b^(m-1) + c2*b^(m-2) + . . . + c0*b^0 意为将字符串C当做 b进制数 来处理,b是基数;
(3) 关于对 h 取模,若b,h有公因子,那么不同的字符串取余之后的结果发生冲突的几率将大大大增加(冲突:数值相同的意
思)
】;
4》计算上一步H(C)的过程是递归实现的:H(C,k)为前 k 个字符构成的字符串的哈希值,(若不考虑取模):
H(C,k+1)= H( C , k ) * b+c( k+1 );
5》判断 主串上 长度为 n 的任意子串 C '=c(k+1) c(k+2) c(k+3) . . . c(k+n) 与 待匹配串S=s1 s2 s3. . .sn 的哈希值是否相等【现在子串长度为n!!】,则:
H(C ’)= H( C , k+n ) - H(C, k ) * b^n;
【我全部都看明白之后还是有点懵,感觉和用遍历没什么差别,,看看了看分析,因为运算是递归的,所以主串中前 i 字符的哈希值是打表存储好的,取子串时直接调用相减函数就可以,此时需要计算的只有b^n,还是省去很多比对的过程的】
6》思路在第五步就已经结束了,我看完也在翘首期盼着“考虑取模”的讲解,其实在实际应用中,通常利用32/64位无符号整数来计算哈希值的,这样的话,当哈希值溢出时,系统会自动对h=2^32 / h=2^64取模。
对于哈希值在 0~n 内均匀分布的哈希函数,出现不同字符串哈希值相等的期望步数是O(sqrt(n)),这在选择哈希函数时可以作为一个效率和正确性的参考。
即便如此,我们还可以再用双哈希降低出现相同哈希值的概率,即取不同的模数,把不同的模数算出来的哈希值都记下来,只有几个哈希值都一样,我们才能判定字符串的匹配,我们通常用双哈希就可以相冲突的概率降到最低,如果分别取 h1=10^9+7和h=10^9+9,就几乎不可能发生冲突,因为他们是一对孪生质数。