小编典典

为所有字谜生成相同的唯一哈希码

algorithm

最近,我参加了一次采访,面对有关哈希冲突的一个很好的问题。

问题:给定一个字符串列表,一起打印出字谜。

示例:

i / p:{行为,神,动物,狗,猫}

o / p:行为,猫,狗,神

我想创建哈希图并将单词作为键并将值作为字谜列表

为了避免冲突,我想为字谜生成唯一的哈希码,而不是对单词进行排序并将其用作键。

我正在寻找哈希算法,该算法除了使用链接外还可以解决冲突。我希望算法为act和cat生成相同的哈希码…,以便它将下一个单词添加到值列表中

谁能建议一个好的算法?


阅读 205

收藏
2020-07-28

共1个答案

小编典典

使用排序后的字符串进行哈希处理非常好,我可能已经做到了,但是确实很慢且麻烦。这是另一种想法,不确定是否可行-
选择一组尽可能小的素数,与字符集大小相同,并从字符到字符建立快速映射功能。然后对于给定的单词,将每个字符映射到匹配的质数中,然后相乘。最后,使用结果进行哈希处理。

这与Heuster提出的建议非常相似,只是发生了较少的碰撞(实际上,考虑到任意数量的素数分解的唯一性,我相信不会有错误的碰撞)。

简单例如-

int primes[] = {2, 3, 5, 7, ...} // can be auto generated with a simple code

inline int prime_map(char c) {
    // check c is in legal char set bounds
    return primes[c - first_char];
}

...
char* word = get_next_word();
char* ptr = word;
int key = 1;
while (*ptr != NULL) {
    key *= prime_map(*ptr);
    ptr++;
}
hash[key].add_to_list(word);

[编辑]

关于唯一性的几句话-
任何整数对素数的乘法都有一个分解,因此给定哈希中的整数键,您实际上可以重构所有可能对其进行哈希的字符串,仅这些单词即可。只需分解为素数,p1 ^ n1 * p2 ^ n2 * …并将每个素数转换为匹配的char。p1的char将出现n1次,依此类推。您无法获得未明确使用的任何新素数,成为素数意味着您无法通过其他素数的任何乘积来获得它。

这带来了另一个可能的改进-
如果可以构造字符串,则只需标记填充哈希时看到的排列。由于可以按字典顺序对排列进行排序,因此可以将每个数字替换为一个数字。这样可以节省将实际字符串存储在哈希中的空间,但是将需要更多的计算,因此不一定是一个好的设计选择。尽管如此,它还是原始问题的一个很好的复杂之处:)

2020-07-28