std::hash<std::string> 可以为不同的字符串返回相同的值吗?

Can std::hash<std::string> return the same value for different strings?

本文关键字:std 字符串 返回 lt hash string gt      更新时间:2023-10-16

下面的链接提到了碰撞的机会,但我正在尝试使用它来查找重复条目:

http://www.cplusplus.com/reference/functional/hash/

我正在使用std::hash<std::string>并将返回值存储在 std::unordered_set 中。 如果 emplace 失败,我将字符串标记为重复字符串。

哈希通常是从大空间的值到小空间的值的函数,例如从所有字符串的空间到 64 位整数。字符串比 64 位整数多得多,因此显然多个字符串可以具有相同的哈希值。一个好的哈希函数是这样的,没有简单的规则将具有相同哈希值的字符串相关联。

因此,当我们想使用哈希来查找重复的字符串(或重复的任何内容(时,它始终是一个两阶段的过程(至少(:

  1. 查找具有相同哈希的字符串(即找到字符串的"哈希桶"(
  2. 将字符串与具有相同哈希的其他字符串逐字符比较。

std::unordered_set这样做 - 从不介意细节。请注意,它会为您执行此操作,因此您可以自己散列,然后将结果存储在std::unordered_set中。

最后,请注意,还有其他功能可用于初始重复筛选 - 或在相同的哈希值中进行搜索。例如,字符串长度:在逐个字符比较两个字符串之前,请检查它们的长度(您应该能够在不实际迭代字符串的情况下访问它们(;不同的长度 ->不相等的字符串。

是的,两个不同的字符串可能会共享相同的哈希。简单地说,假设你有一个存储在 8 位类型 (unsigned char的哈希值。 即 2^8 = 256 个可能的值。这意味着您只能有 256 个任意输入的唯一哈希。
由于您绝对可以创建超过 256 个不同的字符串,因此哈希不可能对所有可能的字符串都是唯一的。

std::size_t是 64 位类型,因此如果您将其用作哈希值的存储,您将有 2^64 个可能的哈希,略多于 256 个可能的唯一哈希,但仍然不足以区分您可以创建的所有可能字符串。

您只是无法仅以 64 位存储整本书。

是的,它可以为不同的字符串返回相同的结果。这是将无限范围的可能性减少到单个 64 位数字的自然结果。

存在称为"完美哈希函数"的东西,它会产生一个将返回唯一结果的哈希函数。但是,这仅保证用于一组已知的输入。来自外部的未知输入可能会生成匹配的哈希数字。通过使用布隆过滤器可以减少这种可能性。

但是,在所有这些哈希计算的某个时候,程序最好在未排序的线性数组中进行简单的字符串比较。谁在乎操作是否O(1)+CC是否大得离谱。

是的,std::hash为不同的std::string返回相同的结果。 不同的编译器对存储桶的创建是不同的。

基于编译器的实现可在链接中找到: 针对 std::unordered_set 的哈希和重新哈希