在哈希表中查找冲突
Posted
技术标签:
【中文标题】在哈希表中查找冲突【英文标题】:Finding collisions in hash table 【发布时间】:2012-05-24 15:36:01 【问题描述】:我正在复习我的数据结构期末考试,在去年的期末考试中遇到了一个问题。在过去三个小时的工作中,我仍然无法找到解决它的方法,除非通过反复试验。问题来了:
"假设你的哈希表的大小是31,常数g也是31,并且你使用下面的哈希码
int hash = 0;
int n = s.length();
for (int i = 0; i < n; i++)
hash = g * hash + s.charAt(i);
并且您使用单独的链接来解决冲突。列出五个不同的名称,它们将散列到表中的同一位置。”
我认为必须有某种技巧,可能涉及模运算符来解决这个问题,考虑到哈希表的大小是 31,与常数 g 相同。对不起,如果我听起来像这样,但我不是要代码或任何东西,只是对这个问题的一些想法/提示。非常感谢任何评论。谢谢
【问题讨论】:
【参考方案1】:java 字符串可以包含零字符 ("\0"
),因此以下所有内容都将哈希为相同的值:
"a"
"\0a"
"\0\0a"
"\0\0\0a"
"\0\0\0\0a"
这是证明(感谢 Eric 提供的参考,这是使用的哈希):
> cat Foo.java
class Foo
public static void main(String[] args)
System.out.println("a".hashCode());
System.out.println("\0a".hashCode());
System.out.println("\0a".length());
System.out.println("\0a".equals("a"));
> javac Foo.java
> java Foo
97
97
2
false
不过,我怀疑这是预期的答案。
另外,如果这是一场考试,我怀疑我是否能记住 ASCII 码。所以在另一个答案中使用样式序列的另一种方法是:
"\002\000"
"\001\037"
等(这些是八进制三元组 - 以上都哈希到 62)。但是为这种风格生成 5 个 个示例(所有相同的哈希)是否容易?
【讨论】:
是的,我不认为这是预期的答案哈哈,但仍然非常感谢!我学到了一个关于零字符的新东西,这太棒了。【参考方案2】:根据Wikipedia article on Java's string hashing algorithm(和你提出的算法一样):
与任何一般的散列函数一样,冲突是可能的。为了 例如,字符串“FB”和“Ea”具有相同的哈希值。这 String 的 hashCode() 实现使用素数 31 和 'a' 和 'B' 的差值只有 31,所以计算结果是 70 × 31 + 66 = 69 × 31 + 97。
【讨论】:
顺便说一句,这种散列实现使 Java 容易受到 DoS 攻击!有关使用哈希映射的 DoS 攻击,请参阅 ocert.org/advisories/ocert-2011-003.html、cryptanalysis.eu/blog/2011/12/28/… 或 google。 @yshavit:很有趣。我以前没有考虑过,但它很有意义。 更多为String.hashCode
生成冲突的方法:david-soroko.blogspot.co.uk/2015/06/…以上是关于在哈希表中查找冲突的主要内容,如果未能解决你的问题,请参考以下文章