哈希整数序列

时间:2013-05-22 15:02:40

标签: hash

我必须处理数字序列,其中序列具有以下属性:

  • 元素是整数,
  • 序列的长度各不相同,并且不固定,
  • 整数有一个上限,
  • 允许多次出现元素,
  • 元素的顺序无关紧要。

给定一个序列,我想知道这个序列是否已经发生,那就是我想要哈希序列。例如,

[2, 3, 6, 2, 13]

[6, 3, 2, 13, 2]

应具有相同的哈希值。

使用的编程语言是C.

我知道我可以先对序列进行排序,然后将它们存储在trie中,这绝对是一种选择。然而,为此目的,什么是适当的哈希函数?

2 个答案:

答案 0 :(得分:3)

要求

  
      
  • 元素的顺序无关紧要
  •   

让我立刻想到Zobrist hashing之类的东西。也就是说,你有一个函数f将整数映射到随机位串,你的散列就是与序列中数字对应的位串的XOR。

当然,上面描述的基本Zobrist哈希不能满足你的其他要求

  
      
  • 允许多次出现元素
  •   

因为XOR运算是它自己的反转(即任何a XOR a = 0的{​​{1}})。但是,简单地用一些其他ring操作替换XOR而没有这个属性(在正常的Zobrist散列中,实际上被认为是可取的),例如 n -bit的加法,应该产生类似的散列你想要的:

a

(关于这个函数的一个小细节是,如果你想截断它的输出,使用高位而不是低位稍微好一点。这是因为,如果 k 最低序列unsigned int hash_multiset (int *seq, int n) { unsigned int h = 0; while (n--) h += f( *seq++ ); return h; } [a]的哈希比特会发生冲突, k [b][a, a],{{1}的最低位也会发生冲突对于 k 最高位,这不是真的,因为较低的位可以转移到较高的位,产生更多的“随机”输出。)

有多种方法可以实现函数[b, b]。对于有限范围的输入整数,您可以简单地使用随机位串的固定查找表。或者,如果您事先不知道输入的范围,则可以使用另一个(普通)哈希表将整数映射到随机位串,然后“动态”构建它。

最后,也可以在没有查找表的情况下实现[a, b] ,只需使用“看起来足够随机”的固定函数即可。这种功能的一个好选择是使用简单快速的block cipher,例如TEA或(在具有硬件支持的系统上)AES,输出被截断为你的首选哈希长度。

答案 1 :(得分:1)

如何将序列的所有数字和长度相乘,以一些相当大的数量为模?这是一些显示计算的Scala代码:

val l = List(6, 3, 2, 13, 2)
(l.reduce(_ * _) * l.length) % 10000

结果为:4680。

显然,这并不能保证如果哈希匹配,则序列是唯一的。 (它甚至可能不是一个非常好的近似值!)但是,如果哈希匹配,则保证序列不相同。