【发布时间】:2014-10-21 01:06:42
【问题描述】:
我正在尝试编写一个(完美的)哈希表来压缩来自unicode codepoint names to their codepoint number 的映射(将第二列映射到第一列)。如您所见,可能的输入非常有限,实际上字母表中正好有 38 个字符:AB...YZ、0...9、- 和空格。此外,还有很多(子字符串)重复,DIGIT ZERO、DIGIT ONE、...、LATIN CAPITAL LETTER A、LATIN CAPITAL LETTER B 等。
完美的哈希表是通过选择种子S,然后尝试构造一个完美的哈希表(以某种方式)通过S 播种哈希器来计算的。如果无法创建表,则使用新种子重试。有很多冲突通常需要更多的重试,因为算法很难让所有东西都适合。
这样做的结果是我的输入域熵低,创建表需要使用 DJB2 之类的简单哈希函数进行大量重试;像 FNV 这样更好的哈希器运行良好,但像 SipHash 这样更复杂和更慢的函数似乎需要更少的平均重试次数。
由于这完全是静态的和预先计算的,我不太担心质量的质量(即运行时任意输入的安全性和概率分布无关紧要),但更高质量的函数减少了所需的预先计算时间相反,给定的压缩级别允许我在某个固定时间内实现更高的压缩。
问题:是否有有效的已发布哈希函数调整为具有这样的域约束的输入?也就是说,是否有哈希函数利用额外的结构来做更少的操作但仍然获得合理的输出?
我搜索了“字母数字哈希函数”之类的内容,但结果是不相关的(主要是生成一个字母数字字符串作为哈希函数的输出);甚至一些关于正确术语的指导,以便我可以搜索论文也会有所帮助。
(这个问题的动机是解决起来有点有趣,实际上没有必要。)
【问题讨论】:
-
您想要 27268 个项目的完美哈希?对我来说似乎很难。为什么不直接使用 standard 哈希函数来处理冲突? (并且可能使用低填充因子)
-
@wildplasser 它工作正常,生成可能只需要一点时间。例如。 this array 是哈希表本身:使用输入字符串的哈希作为该表的索引(然后验证它是否正确)。这个问题的重点是通过尽可能少的工作来利用输入的结构更快。另外,这是为了压缩,所以低负载系数不好。
-
@wildplasser 最后,请注意我目前使用的是标准哈希函数(我实际上在问题中提到了三个)。
-
输入字母的低基数(约 5.5 位)并不重要,只要散列函数中有足够的雪崩效应。 (不变的)两个前导零不应混淆“标准”哈希函数。我刚刚检查过,我自己的 shift&xor 哈希函数在 38 个字符的字母表上和在完整的 ~7 位 ascii 集上一样好。问题:您是在优化空间还是速度(溢出链只需要一个指针+每个条目一位)?
-
@wildplasser 优化空间,但这是通过优化速度来完成的。这里的瓶颈是生成表,其中包括随机选择哈希种子并尝试构建一个有效的哈希表。对于高压缩因子,可能需要尝试许多种子,因为它们通常不起作用,这可能需要很长时间。如果哈希函数可以通过利用输入结构更有效,我将能够在更短的时间内更多地压缩表。 (这个问题主要是出于兴趣,因为我总是可以把 CPU 时间花在它上面。)
标签: hash alphanumeric