字符串Hash的原理与应用
字符串Hash無論是在ACM競賽中還是在工程中都有著廣泛的應(yīng)用,所以很有必要掌握好它的用法。主要分為兩個部
分:Hash映射和沖突處理。而本文主要來詳細(xì)講解Hash映射的方法及應(yīng)用,下篇文章將會介紹如何處理沖突。
?
對于字符串Hash來說都是把字符串映射為一個整數(shù),這一步是通過Hash函數(shù)來進(jìn)行的。常用的Hash函數(shù)具體有:
SDBMHash,RSHash,JSHash,ELFHash,BKDRHash,DJBHash等等。接下來只詳細(xì)介紹ELFHash函數(shù)的原理
及應(yīng)用。
?
ELFHash函數(shù)的代碼如下
unsigned int ELFhash(char *str) {unsigned int h = 0;unsigned int x;while(*str){h = (h << 4) + *str++;x = h & 0xF0000000L;if(x){h ^= x>>24;h &= ~x;}}return h & 0x7FFFFFFF; }接下來我會詳細(xì)探討它的原理。
?
(1)h = (h << 4) + *str++;? 把當(dāng)前的字符的ASCII存入h的低4位。
(2)x = h & 0xF0000000L;??? 取出h中最高4位,0xF0000000L地代表28~31這4位是1,其余后28位是0。
(3)如果最高4位不為0,那么說明字符多于7個,現(xiàn)在正在存第8個,如果不處理再加下一個字符時,第一個字符會
??? 被移出,因為1~4位剛剛加入了新字符,所以不能>>28,而是>>24。
(4)h &= ~x;??????????????? 表示把h的高4位清零。
?
題目:http://acm.hdu.edu.cn/showproblem.php?pid=1800
?
題意:給定一些數(shù)字,可能有前導(dǎo)零,求這些數(shù)字中出現(xiàn)次數(shù)最多的數(shù)字的次數(shù)。
?
代碼:
#include <iostream> #include <string.h> #include <stdio.h>using namespace std; const int N = 1000005; const int MOD = 100007;int hash[N], cnt[N];unsigned int ELFhash(char *str) {unsigned int h = 0;unsigned int x;while(*str){h = (h << 4) + *str++;x = h & 0xF0000000L;if(x){h ^= x>>24;h &= ~x;}}return h & 0x7FFFFFFF; }int HashHit(char *str) {while(*str == '0') str++;int k = ELFhash(str);int t = k % MOD;while(hash[t] != k && hash[t] != -1)t = (t + 10) % MOD;if(hash[t] == -1){cnt[t] = 1;hash[t] = k;}else cnt[t]++;return cnt[t]; }int main() {int n;char str[105];while(scanf("%d", &n)!=EOF){int ans = 1;memset(hash,-1,sizeof(hash));while(n--){scanf("%s", str);ans = max(ans, HashHit(str));}printf("%d\n", ans);}return 0; }
?
問題:為什么Hash表的size總是擴(kuò)展成一個素數(shù)?
?
分析:素數(shù)可以有效地減少沖突。具體原因如下
???? 假設(shè)Hash表的大小為size,這是一個合數(shù),即有size = a * n,當(dāng)有Hash值為HashCode = b * n,則
?????HashCode取模之后有
?
????
?
???? 因為是固定不變的,那么HashCode取值就有了種可能,這樣顯然會增加沖突的概率。
?
?
總結(jié)
以上是生活随笔為你收集整理的字符串Hash的原理与应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU4741(异面直线间的距离--空间
- 下一篇: POJ1177矩形面积并(矩形切割+括号