【问题标题】:Hashing Sequences of Integers散列整数序列
【发布时间】:2013-05-22 15:02:39
【问题描述】:

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

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

给定一个序列,我想知道这个序列是否已经发生,即我想对序列进行哈希处理。例如,

[2, 3, 6, 2, 13]

[6, 3, 2, 13, 2]

应该具有相同的哈希值。

使用的编程语言是 C。

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

【问题讨论】:

  • 所以它们真的比序列更多,对吧?既然顺序无关紧要?
  • 一个普通的旧 XOR 将是一个合理的起点。
  • “整数可能有一个事先不知道的上限”...如果有有限多个集合,并且每个集合的大小有限,那么您可以更具体并声明“整数肯定有一个上限……”。虽然我不完全确定这个事实是否真的与这个问题有关。一个想法是将每个集合放入某种规范形式(例如对其进行排序),并生成一个良好的哈希(MD5,SHA-*,取决于您期望拥有多少),并存储它。 /跨度>
  • hash = a[0] xor a[1] xor a[2] xor a[3] xor ...
  • 需要注意的重要一点是,无论顺序如何,您都需要相同的哈希值。这意味着您要么需要一个不区分顺序的散列,要么需要在散列之前将元素按规范顺序放置(即对它们进行排序)。不区分顺序的散列将是加法(带有溢出)、XOR 和一些分类的 bit-bashing 技术。 “罐装”哈希算法通常(按设计)不是顺序不敏感的,这意味着您必须在应用它们之前进行排序。

标签: hash


【解决方案1】:

要求

  • 元素的顺序无关紧要

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

当然,上面描述的基本 Zobrist 散列不能满足您的其他要求

  • 允许元素多次出现

因为 XOR 运算是它自己的逆运算(即 a XOR a = 0 对应于任何 a)。但是,简单地将 XOR 替换为没有此属性的其他一些 ring 操作(在正常的 Zobrist 散列中,这实际上被认为是可取的),例如 n 位加法,应该会产生你想要的散列:

unsigned int hash_multiset (int *seq, int n) {
    unsigned int h = 0;
    while (n--) h += f( *seq++ );
    return h;
}

(关于这个函数需要注意的一个小细节是,如果你想截断它的输出,使用高位比使用低位稍微好一点。这是因为,如果 k 最低序列[a][b] 的哈希位发生冲突,那么[a, a][b, b][a, b] 等的k 个最低位也会发生冲突。对于 k 个最高位,这是不正确的,因为较低位可以转移到较高位,从而产生更多“随机”输出。)

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

最后,也有可能实现f 没有查找表,只需使用“看起来足够随机”的固定函数即可。这种函数的一个不错的选择是使用简单而快速的block cipher,例如TEA 或(在硬件支持的系统上)AES,并将输出截断为您喜欢的哈希长度。

【讨论】:

  • 这看起来很有趣,谢谢。 n = 序列长度吗?
  • 是的。 C 数组不存储自己的长度,因此您需要以某种方式将其传递给函数。
【解决方案2】:

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

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

这导致:4680。

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

【讨论】:

  • 这个想法的整数 mod 组件几乎可以保证,如果我有 10000 个或更多序列,我将有错误的碰撞。
  • 谢谢,这似乎是一种选择。
猜你喜欢
  • 2013-06-25
  • 2012-10-02
  • 2010-10-14
  • 2014-05-19
  • 2013-07-20
  • 2012-07-22
  • 1970-01-01
  • 1970-01-01
  • 2016-02-14
相关资源
最近更新 更多