std::hash<std::string> 可以为不同的字符串返回相同的值吗?
Can std::hash<std::string> return the same value for different strings?
下面的链接提到了碰撞的机会,但我正在尝试使用它来查找重复条目:
http://www.cplusplus.com/reference/functional/hash/
我正在使用std::hash<std::string>
并将返回值存储在 std::unordered_set 中。 如果 emplace 失败,我将字符串标记为重复字符串。
哈希通常是从大空间的值到小空间的值的函数,例如从所有字符串的空间到 64 位整数。字符串比 64 位整数多得多,因此显然多个字符串可以具有相同的哈希值。一个好的哈希函数是这样的,没有简单的规则将具有相同哈希值的字符串相关联。
因此,当我们想使用哈希来查找重复的字符串(或重复的任何内容(时,它始终是一个两阶段的过程(至少(:
- 查找具有相同哈希的字符串(即找到字符串的"哈希桶"(
- 将字符串与具有相同哈希的其他字符串逐字符比较。
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)+C
C是否大得离谱。
是的,std::hash
为不同的std::string
返回相同的结果。 不同的编译器对存储桶的创建是不同的。
基于编译器的实现可在链接中找到: 针对 std::unordered_set 的哈希和重新哈希
- 我可以重新分配/覆盖std::字符串吗
- 如何将这个std::字符串转换为std::基本字符串
- std::字符串与 PCWSTR 的对话
- 重载 std::字符串运算符+ 用于打印枚举名称
- 从std::字符串创建OssBitString
- std::字符串擦除以删除最后一个字母
- 如何使用 C++ 中的原语初始化类(如 std::字符串从 const char* 初始化)
- std::字符串串联操作
- 如何有效地将一个大std::字符串的一部分转换为float
- 转义std::字符串中的特殊字符
- 用C++替换std::字符串中的一个子字符串,但不能全部替换
- C++std::字符串流到常量字符*的转换
- 如何将std::字符串转换为不同的字符串类
- 对齐C++字符串类型问题 std::字符串到 TStr
- std::字符串到字符*而不切割字节
- 编写具有非ASCII数据的std ::字符串
- 将 Delphi 的字符串转换为 std::字符串用于C++
- std::字符串添加到字符*
- 字符* 和 std::字符串和常量字符*之间的转换
- 用指针访问std ::字符串中的元素