为了加快测试字谜字符串的快速行为,我came up with基于素数的哈希方案 - 虽然它看起来像我wasn't the first。
基本思想是将字母映射到素数,并计算这些素数的乘积。任何重新排列的字母都会有相同的产品,如果结果可以任意大,那么其他字母的组合也不会产生相同的结果。
我最初设想这是只是哈希。最终产品会溢出并开始为其他字母组合添加别名。但是,通过将最频繁的字母映射到最小的素数,产品生长缓慢并且通常可以完全避免溢出。在这种情况下,我们得到一个完美的哈希,给出明确的正面和负面结果,无需额外的测试。
值得注意的是,它在溢出之前没有非常有效地填充编码空间。没有结果会有任何大于103的素数因子,并且小素数的分布是固定的,并不一定与字母频率匹配。
现在我想知道是否有比这更好的东西。在剩下的情况下,包含更多结果的东西具有完美的散列并且具有强烈的分布。
我能想到的最密集的编码方案是对字母进行排序,然后用熵编码器将它们打包成一个单词。在该方案中,由于应用于每个位置的范围约束,字母频率显然会极大地偏向(例如,以z开始的排序数组的可能性显着低于以z结尾的排序数组的可能性。)
这听起来像是一大堆工作 - 而且我看不出它能保证在溢出的情况下提供良好的分配。
也许有一组更好的因素来映射字母,以及更好的方法来检测何时开始出现混叠风险。还是一个不依赖于乘法的哈希方案?什么东西很容易计算?
那就是:
英语语言限制(26个具有典型英语单词结构的字母)会很好。多字节编码方案是另一个问题。
C代码首选,因为我理解它。
答案 0 :(得分:1)
如果您使用大小为m的字母表的n位哈希值,则可以使用我所描述的方法here为长达(n-m)个字符的字谜提供唯一的哈希值。这样就不需要进行碰撞检测,但它会根据字母表的大小和可用空间来限制字数。
为了允许任何长度的单词,我将使用n-1位为长度为(n-m-1)个字符的单词执行该散列,并保存最后一位以表示该单词为m个字符或更长。在这些情况下,您将使用剩余的n-1位作为素数或其他散列算法,但当然,只要您在这些存储桶中有多个单词,就可以进行碰撞检测。由于在实际应用中大多数单词将占用较短的单词长度,因此您将大大减少较长单词所需的碰撞检测。
答案 1 :(得分:0)
在此处实施了flancor的答案:https://github.com/sh1boot/anagram/blob/master/bitgram.c
使用http://ftp.debian.org/debian/pool/main/s/scowl/wbritish_7.1-1_all.deb作为 字典,我得到以下比例的完美代码(积极的和 来自哈希比较的负匹配)使用这些编码方案:
order | frequency| alphabet| frequency| alphabet| frequency
code | prime | unary | unary | huffman | huffman
-------|----------|----------|----------|----------|----------
64-bit | 93.95% | 100.00% | 100.00% | 100.00% | 100.00%
32-bit | 24.60% | 69.14% | 74.23% | 86.57% | 90.58%
28-bit | 15.20% | 41.75% | 60.27% | 68.16% | 74.34%
24-bit | 8.21% | 13.14% | 38.55% | 42.67% | 50.34%
20-bit | 3.72% | 3.35% | 16.73% | 19.41% | 25.59%
16-bit | 1.31% | 0.82% | 4.86% | 5.51% | 9.18%
这表明任何比特打包直方图编码的变体都可以捕获 完整的64位哈希中的整本字典,以及超过三分之二的字典 32位哈希中的字典;而主要产品计划正在努力 即使在64位也达到100%,甚至不能覆盖四分之一的字典 一个32位的哈希。
这个列表确实包含很多撇号,但几乎所有(但不是 所有)64位未命中包括撇号。把这个角色放在其中 频率表中的适当位置可能会有所帮助。
一些additional测试:
频率/霍夫曼,溢出:
88aff7eb53ef9940: Pneumonoultramicroscopicsilicovolcanoconiosis
频率/霍夫曼,64位完美:
17415fbc30c2ebf7: Chargoggagoggmanchauggagoggchaubunagungamaugg
018a6b5dda873fba: Supercalifragilisticexpialidocious
00021ae1bcf50dba: Pseudopseudohypoparathyroidism
00070003dd83b5fb: Floccinaucinihilipilification
00002b800ebbdf7a: Antidisestablishmentarianism
000006c6ab75b3f9: Honorificabilitudinitatibus
0000000421b2ad94: glyptoperichthys
0000000201b2ad94: pterygoplichtys
可能的情况是,应该针对可能落在边界附近的单词进行调整,因为它们可能具有强烈影响其分布的属性(例如,原始语言),并且使得更短的单词更长。直到它们溢出为止。