所以我的教授刚刚分配了this家庭作业。我知道我对哈希技术的分享,但是我完全不知道如何不因冲突而失去很多分数,因为1百万字符串会在我的哈希表中暴力冲突。
我应该关注什么?
或许我只是完全误解了作业。你们怎么去解决这个问题呢?任何想法都会非常有用。
答案 0 :(得分:1)
您的老师要求您散列100万个字符串,并且您有2 ^ 32 = 4,294,967,296个不同的32位整数值。
使用20个字符的随机字符串,大量可能的字符串比哈希值更多,因此不能将特定字符串映射到特定哈希值,以限制碰撞潜力(也就是说你有< = 2 ^ 32个潜在的字符串,因为字符串长度较短,或者每个字符被允许采取的值受到限制 - 你有机会获得完美的哈希函数:一个公式映射每个一个已知的不同数字)。
因此,您基本上不得不尝试随机但可重复从字符串映射到哈希值。随之而来的是“生日悖论”,这意味着你必须期待相当多的碰撞。多少?好吧 - this answer提供了公式 - 对于 m 存储桶(2 ^ 32)和 n 插入(1,000,000):
expected collisions = n - m * (1 - ((m-1)/m)^n)
= 1,000,000 - 2^32 * (1 - ((2^32 - 1) / 2^32) ^ 1,000,000)
= 1,000,000 - 2^32 * (1 - 0.99976719645926983712557804052625)
~= 1,000,000 - 999883.6
~= 116.4
换句话说,对于随机字符串输入,平均最好的哈希函数将会有116次冲突。
你的老师说:
最终得分为最高{0,200-5 * T}
所以,完成这项任务是没有意义的:你更有可能在前花园里拥有一块24克拉的金色流星土,而不是获得正分。
也就是说,如果你想为这个类实现最少的冲突次数,那么低性能(不是特别是缓存友好)但最小的冲突选项就是拥有一组随机数据......
uint32_t data[20][256] = { ... };
从互联网网站下载一些真正随机的数据以填充它。丢弃任何重复的数字(在C ++中,您可以使用std:set<>
来查找它们)。逐个字符位置(0..19)然后是字符值,通过对值进行异或来生成散列。
如果不相信上述信息,您可以生成一百万个随机32位值 - 就好像它们是不同字符串的哈希值 - 并查看哈希值重复的频率。任何给定的运行应该产生的输出与上面计算的116碰撞平均值相差不远。
#include <iostream>
#include <map>
#include <random>
int main()
{
std::random_device rd;
std::map<unsigned, int> count;
for (int i = 0; i < 1000000; ++i)
++count[rd()];
std::map<int, int> histogram;
for (auto& c : count)
++histogram[c.second];
for (auto& h : histogram)
std::cout << h.second << " hash values generated by " << h.first << " key(s)\n";
}
一些运行产生了输出......
$ ./poc
999752 hash values generated by 1 key(s)
124 hash values generated by 2 key(s)
$ ./poc
999776 hash values generated by 1 key(s)
112 hash values generated by 2 key(s)
$ ./poc
999796 hash values generated by 1 key(s)
102 hash values generated by 2 key(s)
$ ./poc
999776 hash values generated by 1 key(s)
112 hash values generated by 2 key(s)
$ ./poc
999784 hash values generated by 1 key(s)
108 hash values generated by 2 key(s)
$ ./poc
999744 hash values generated by 1 key(s)
128 hash values generated by 2 key(s)
答案 1 :(得分:1)
任务是创建零冲突的哈希函数。 TonyD刚刚将预期的碰撞计算为116.根据评分,对于116次碰撞的散列函数,你将获得零点。
教授提示使用unordered_map
,这对设计哈希函数没有帮助。这可能是一个棘手的问题......
您如何设计一个为100万输入返回可重复的唯一数字的函数?