非常に大きな文字列の n-gram のハッシュを取得できるように、ローリング ハッシュ関数を使用しようとしています。
例えば:
「stackoverflow」を 5 グラムに分割すると、次のようになります。
「stack」、「tacko」、「ackov」、「ckove」、「kover」、「overf」、「verfl」、「erflo」、「rflow」
これはローリング ハッシュ関数に最適です。最初の n グラム ハッシュを計算した後、最初のハッシュの最初の文字を削除し、2 番目のハッシュの新しい最後の文字を追加するだけで済むため、次のハッシュは比較的安価に計算できます。 .
一般に、このハッシュ関数は次のように生成されることを知っています。
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 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 を使用しています。ハッシュがオーバーフローしても問題ありませんか? これは望ましいと思いますが、よくわかりません。
これはこれを行う正しい方法のように思えますか?