【发布时间】:2011-01-19 19:53:12
【问题描述】:
我希望使用滚动散列函数,这样我就可以对一个非常大的字符串的 n-gram 进行散列。
例如:
“stackoverflow”,分成 5 克是:
"stack", "tacko", "ackov", "ckove", “kover”、“overf”、“verfl”、“erflo”、“rflow”
这对于滚动散列函数是理想的,因为在我计算了第一个 n-gram 散列之后,以下的计算相对便宜,因为我只需删除第一个散列的第一个字母并添加新的最后一个字母第二个哈希。
我知道通常这个哈希函数是这样生成的:
H = c1ak − 1 + c2ak − 2 + c3ak − 3 + ... + cka0 其中 a 是常数,c1,.. .,ck 是输入字符。
如果您点击 Rabin-Karp string search algorithm 上的此链接,它会指出“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 作为我的素数。我的哈希值是否会溢出有关系吗?我认为这是可取的,但我不确定。
这似乎是解决这个问题的正确方法吗?
【问题讨论】:
-
为什么这个应用程序的素数与“正常”字符串哈希码生成有什么不同?
-
算法很简单,很容易用伪代码实现。你试过自己编码吗?
标签: c# java algorithm hash rabin-karp