哈希函数有多好,它是值的线性组合?

时间:2017-08-30 16:39:19

标签: algorithm data-structures hash hashcode

我正在阅读关于哈希的文字,我发现char字符串的天真哈希码可以实现为多项式哈希函数

h(S0,S1,S2,... SN-1)= S0 * A ^ N-1 + S1 * A ^ N-2 + S2 * A ^ N-3 ..... SN-1 * A ^ 0。其中Si是索引i处的字符,A是某个整数。

但我们不能直接总结为

h(S0,S1,S2,... SN-1)= S0 *(N)+ S1 *(N-1)+ S2 *(N-2)...... SN-1 * 1。

我也看到这个功能也很好,因为两个值2 * S0 + S1!= 2 * S1 + S0(它们是反向的)没有被散列到相同的值。但是我找不到这种类型的哈希函数

2 个答案:

答案 0 :(得分:3)

假设我们使用30个字符的字符串。这不长,但它并不短,以至于哈希的问题应该纯粹因为字符串太短而出现。

权重之和为465(1 + 2 + ... + 30),可打印的ASCII字符使得最大哈希值为58590,由" ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~&#34 ;.还有更多可能的打印ASCII字符串,其中包含30个字符(95 30 ≈2E59),但它们都会在0到58590的范围内进行哈希处理。当然,你实际上并不能拥有同时有很多字符串,但是你可能会有超过58590,这可以保证只是基于计数的碰撞(当然很可能会发生很快)。

最大哈希值增长缓慢,在使用32位整数的整个范围之前,您需要3400万个字符串。

另一种方式,乘以A的幂(这可以用Horner的方案来评估,因此不需要明确计算任何权力,它仍然只需要为每个字符添加一个加法和乘法,尽管天真的方式是不是计算该哈希的最快方法),没有这个问题。 A的权力很快变大(并且开始包装,只要A是奇数就很好),所以30个字符的字符串很有可能覆盖你正在使用的任何整数类型的整个范围。

答案 1 :(得分:2)

线性哈希函数的问题在于它更容易产生冲突。

考虑一个包含3个字符的字符串:S0,S1,S2。 建议的哈希码为3 * S0 + 2 * S1 + S2。

每次我们将char S2减少两个(例如 e - > c),并将char S1增加一个(例如 m - > n) ,我们获得相同的哈希码。

即使只是可以如此容易地描述保留散列的操作这一事实也是一个警报(因为某些算法可能会以这种方式处理字符串)。作为一个更极端的例子,考虑只是对人物进行求和。在这种情况下,原始字符串的所有字符串都会生成相同的哈希码(因此,在处理字谜的应用程序中,此哈希将毫无用处。)