我正在寻找使用滚动散列函数,这样我就可以对一个非常大的字符串的 n-gram 进行散列。
例如:
“stackoverflow”,分成 5 克是:
“stack”、“tacko”、“ackov”、“ckove”、“kover”、“overf”、“verfl”、“erflo”、“rflow”
这对于滚动散列函数是理想的,因为在我计算了第一个 n-gram 散列之后,以下的计算相对便宜,因为我只需删除第一个散列的第一个字母并添加第二个散列的新的最后一个字母.
我知道通常这个哈希函数生成为:
H = c 1 a k - 1 + c 2 a k - 2 + c 3 a k - 3 + ... + c k a 0其中 a 是常数,c1,...,ck 是输入字符。
如果您在Rabin-Karp 字符串搜索算法上点击此链接,它会指出“a”通常是一些大素数。
我希望我的散列存储在 32 位整数中,那么“a”应该有多大的素数,这样我就不会溢出我的整数?
是否存在我已经可以使用的该哈希函数的现有实现?
这是我创建的一个实现:
public class hash2
{
public int prime = 101;
public int hash(String text)
{
int hash = 0;
for(int i = 0; i < text.length(); i++)
{
char c = text.charAt(i);
hash += c * (int) (Math.pow(prime, text.length() - 1 - i));
}
return hash;
}
public int rollHash(int previousHash, String previousText, String currentText)
{
char firstChar = previousText.charAt(0);
char lastChar = currentText.charAt(currentText.length() - 1);
int firstCharHash = firstChar * (int) (Math.pow(prime, previousText.length() - 1));
int hash = (previousHash - firstCharHash) * prime + lastChar;
return hash;
}
public static void main(String[] args)
{
hash2 hashify = new hash2();
int firstHash = hashify.hash("mydog");
System.out.println(firstHash);
System.out.println(hashify.hash("ydogr"));
System.out.println(hashify.rollHash(firstHash, "mydog", "ydogr"));
}
}
我使用 101 作为我的素数。我的哈希值是否会溢出有关系吗?我认为这是可取的,但我不确定。
这似乎是解决这个问题的正确方法吗?