Hash 理解循环多项式散列冲突

Hash 理解循环多项式散列冲突,hash,n-gram,hash-collision,Hash,N Gram,Hash Collision,我有一段代码,它使用循环多项式滚动散列(Buzhash)来计算n克源代码的散列值。如果我使用小散列值(7-8位),则会出现一些冲突,即不同的n-gram映射到相同的散列值。如果我将散列值中的位增加到31,那么会有0个冲突-所有NGRAM映射到不同的散列值 我想知道为什么会这样?冲突是否取决于文本中n-gram的数量或n-gram可以包含的不同字符的数量,还是n-gram的大小 在对n-gram进行散列(使用滚动散列)时,如何选择散列值的位数?长度如何影响冲突 这只是一个排列问题 如果我使用小散列

我有一段代码,它使用循环多项式滚动散列(Buzhash)来计算n克源代码的散列值。如果我使用小散列值(7-8位),则会出现一些冲突,即不同的n-gram映射到相同的散列值。如果我将散列值中的位增加到31,那么会有0个冲突-所有NGRAM映射到不同的散列值

我想知道为什么会这样?冲突是否取决于文本中n-gram的数量或n-gram可以包含的不同字符的数量,还是n-gram的大小

在对n-gram进行散列(使用滚动散列)时,如何选择散列值的位数?

长度如何影响冲突

这只是一个排列问题

如果我使用小散列值(7-8位),那么会有一些冲突

好吧,让我们分析一下。对于8位,可以为任何给定输入生成
2^8
可能的二进制序列。也就是说,可以生成256个可能的哈希值,这意味着理论上,生成的每个
256
消息摘要值都会保证冲突。这就是所谓的生日问题

如果我将散列值中的位增加到31,那么会有0个冲突-所有NGRAM映射到不同的散列值

好吧,让我们用同样的逻辑。对于31位精度,我们有
2^31
可能的组合。即
2147483648
可能的组合。我们可以将其概括为:

Let N denote the amount of bits we use.
Amount of different hash values we can generate (X) = 2^N

Assuming repetition of values is allowed (which it is in this case!)
这是一个指数增长,这就是为什么用8位,你会发现很多碰撞,而用31位,你会发现很少的碰撞

这对碰撞有什么影响

好的,由于值的数量非常少,并且这些值中的每一个都有均等的机会映射到输入,因此:

Let A denote the number of different values already generated.
Chance of a collision is: A / X 

Where X is the possible number of outputs the hashing algorithm can generate.
X
等于
256
时,第一次发生碰撞的几率为
1/256
。然后,当生成不同的值时,发生冲突的几率为
2/256
。直到最后,您已经生成了255个不同的值,并且有发生冲突的可能性。下一次,很明显,它变成了一个
256/256
机会,或者
1
,这是一个概率确定性。显然,它通常不会达到这一点。碰撞可能会比每
256个
周期发生的次数多得多。事实上,生日悖论告诉我们,在生成
2^N/2
消息摘要值之后,我们可以开始预期冲突。按照我们的例子,这是在我们创建了
16
唯一散列之后。然而,我们确实知道,它必须至少每
256个
周期发生一次。这可不好

这意味着,在数学层面上,冲突的可能性与可能的输出数量成反比,这就是为什么我们需要将消息摘要的大小增加到合理的长度

关于散列算法的一点注记


碰撞是完全不可避免的。这是因为,有大量的可能输入(2^所有可能的字符代码),以及有限数量的可能输出(如上所示).

如果散列值为8位,则可能的值总数为256-这意味着如果散列257个不同的n-gram,则肯定至少会有一个冲突(…并且很可能会得到更多的冲突,即使只有257个n-gram)-无论哈希算法或正在哈希的数据如何,都会发生这种情况

如果您使用32位,则可能的值总数约为40亿,因此发生冲突的可能性要小得多

“如何选择位数”:我想这取决于散列的使用。如果它用于将n-gram存储在某种散列数据结构(字典)中,那么它应该与数据结构中可能的“bucket”数量相关-例如,如果字典中的bucket少于256个,那么8位散列就可以了


看一些背景资料

冒着暴露我完全无知的风险。。。较小的散列值不总是更容易发生冲突吗?挑剔:可能输入的数量可能很大,但不是无限的。公平地说,它受到我们可能输入的字符代码数量的限制。Amminding。你可能想提到生日悖论:在你预料到冲突之前,你只需要用N位散列来散列大约2^(N/2)个值。我想我可以。考虑到问题的主题,似乎太多细节了,但为什么不呢。