寻找中等强度的哈希函数

时间:2011-08-30 23:00:50

标签: algorithm hash indexing text-processing

我有一组~35000个唯一的ASCII文本字符串,每个字符串从20到60个字节。我想在其中引入一个独特的索引。由于各种原因,简单编号是不可取的。

像MD5这样的加密级功能可以正常工作,但我觉得这些功能太过分了。这最终是针对移动项目的,所以我对存储和CPU周期都很贪心。另一方面,我尝试过32位Adler32并发生冲突。

有人能想到一个产生64位值的好哈希函数吗?

5 个答案:

答案 0 :(得分:2)

因为您拥有的字符串集是固定的,所以您应该尝试寻找 perfect hash function ,这是一个专门针对一组数据设计的散列函数,以确保不会发生冲突。有很多工具可以创建像这样的哈希函数,其中一个gperf(不要与gprof混淆)我知道它是免费提供的。我强烈建议这样做。

如果您以后最终需要更改字符串集并希望使用轻量级,简单的哈希函数,则可能需要考虑使用 Rabin-Karp rolling hash function 。可以使用O(n)加法,乘法和模数计算长度为n的字符串,并确保每两个字符串具有成对独立的散列值。此外,您可以在大约半小时内对其进行编码,以测试它是否比Adler校验和表现更好。

也就是说,如果你没有尝试实现加密安全性,使用像MD5这样众所周知的哈希函数仍然是一个好主意。在这种情况下,即使是简单的CRC32也可能就足够了。

答案 1 :(得分:1)

鉴于冲突的可能性从64位减少到128位,我强烈考虑使用MD5128。

      Max entries before X chance of collision
Bits  10e−18   10e−15   10e−12   10e−9    10e−6    0.1%     1%       25%      50%      75%
----------------------------------------------------------------------------------------------
16    2        2        2        2        2        11       36       1.9e2    3.0e2    4.3e2
32    2        2        2        2.9      93       2.9e3    9.3e3    5.0e4    7.7e4    1.1e5
64    6.1      1.9e2    6.1e3    1.9e5    6.1e6    1.9e8    6.1e8    3.3e9    5.1e9    7.2e9
128   2.6e10   8.2e11   2.6e13   8.2e14   2.6e16   8.3e17   2.6e18   1.4e19   2.2e19   3.1e19
256   4.8e29   1.5e31   4.8e32   1.5e34   4.8e35   1.5e37   4.8e37   2.6e38   4.0e38   5.7e38
384   8.9e48   2.8e50   8.9e51   2.8e53   8.9e54   2.8e56   8.9e56   4.8e57   7.4e57   1.0e58
512   1.6e68   5.2e69   1.6e71   5.2e72   1.6e74   5.2e75   1.6e76   8.8e76   1.4e77   1.9e77

因此,对于35000(3.5e4)字符串,使用64位散列,这会让您在10e ^ -12和10e ^ -9之间发生碰撞。这可能看起来不是很高,但是当涉及哈希时,十亿分之一很容易被击中。

通过增加到128位,你可以大大减少到1亿(十亿亿)。

答案 2 :(得分:0)

我认为你可以连接两个不同的32位散列函数的值来获得64位散列。

为了获得四种不同的散列函数,我将使用预处理步骤,以某种方式改变散列函数的输入,而不与散列函数中的值进行通信。一种方法是使用256字节的查找表来重新编号字节。另一个可能是将每个字节乘以X mod 257,用-X mod 257替换产生256 = -1 mod 257的任何东西,因为否则不会发生这种情况。注意,(a * 256 + b)mod 257是a + b mod 257.

答案 3 :(得分:0)

FWIW有一个非安全散列函数,有很好的保证。例如,选择一个素数,并以模数为模进行所有计算,这样就可以得到一个数学域。将数据切换为以素数为模的数字序列,并将它们视为多项式的系数。除了为哈希函数选择模数之外,您还可以选择一个数字x mod the prime,然后在该x处计算多项式。理论上,x是随机选取的。

如果多项式的差值为零,则两条消息映射到相同的值,这意味着所选择的x是该多项式的根。 N次多项式最多有N个根,所以在你的情况下 - 如果你有很短的字符串并选择一个大的模数 - 这不是一个坏的保证。我想如果你加密这个计算的结果,我认为这是一个更快的方法来获得安全的哈希函数。我认为它应该比MD5更快,因为即使算术模数128位素数很昂贵,有人认为它比做MD5便宜。

答案 4 :(得分:0)

在64位MurmurHash64B上定居。吹嘘名字的额外点。