Java 为什么要为相同的子字符串生成两个不同的哈希值?我能做些什么来解决这个问题?
我编写了以下代码来尝试Rabin-Karp算法的简单实现Java 为什么要为相同的子字符串生成两个不同的哈希值?我能做些什么来解决这个问题?,java,math,hash,rabin-karp,Java,Math,Hash,Rabin Karp,我编写了以下代码来尝试Rabin-Karp算法的简单实现 public int charToInt(int index, String str){ return (int)str.charAt(index); } public int strStr(String haystack, String needle) { if(needle.length() == 0 ) return 0; int n = needle.length
public int charToInt(int index, String str){
return (int)str.charAt(index);
}
public int strStr(String haystack, String needle) {
if(needle.length() == 0 ) return 0;
int n = needle.length();
int l = haystack.length();
if(n > l) return -1;
//choose large enough prime for hash
final int prime = 257;
//calculate reference hash of needle and first 'n' chars of haystack
long refHash = 0, rollHash = 0;
for(int i = 0; i < n; i++){
refHash += charToInt(i,needle)*(long)Math.pow(prime,i);
rollHash += charToInt(i,haystack)*(long)Math.pow(prime,i);
}
System.out.println("refHash: "+refHash);
System.out.println("rolling hash: "+rollHash);
if(refHash == rollHash) return 0;
for(int i = n; i<l; i++){
// oldhash - old initial char
rollHash -= charToInt(i-n+1, haystack);
// divide by prime.
System.out.println("Perfect division anticipated "+ (double)rollHash/prime);
rollHash /= prime;
// add new char to hash at the end of pattern.
rollHash += (charToInt(i,haystack)*(long)Math.pow(prime,n-1));
if(refHash == rollHash) return i-n+2;
System.out.println("rolling hash: "+rollHash);
}
return -1;
}
输出
stdout:
refHash: 27864
rolling hash: 26061
Perfect division anticipated 101.01167315175097
rolling hash: 27857
Perfect division anticipated 107.9727626459144
rolling hash: 27863
Perfect division anticipated 107.99610894941634
rolling hash: 28634
Answer:
-1
我所希望的是,
Perfect division预期107.9727626459144
此行将输出108,而滚动哈希:27863
滚动哈希将是27864。让我们考虑一下滚动哈希的结构。设A[]
为needle
的字符值的任意数组。在第一个循环之后,rollHash
将
A[0] + prime * A[1] + prime^2 * A[2] + ...
在第二个循环中
for(int i = n; i<l; i++){
// oldhash - old initial char
rollHash -= charToInt(i-n+1, haystack);
// divide by prime.
System.out.println("Perfect division anticipated "+ (double)rollHash/prime);
rollHash /= prime;
....
}
我们不希望它能被素数整除
我认为你犯了一个错误
for(int i = n; i<l; i++){
// oldhash - old initial char
rollHash -= charToInt(i-n, haystack); // **** changed
// divide by prime.
System.out.println("Perfect division anticipated "+ (double)rollHash/prime);
rollHash /= prime;
....
}
for(int i=n;i
A[0] + prime * A[1] + prime^2 * A[2] + ... - A[1]
for(int i = n; i<l; i++){
// oldhash - old initial char
rollHash -= charToInt(i-n, haystack); // **** changed
// divide by prime.
System.out.println("Perfect division anticipated "+ (double)rollHash/prime);
rollHash /= prime;
....
}