Я собираюсь использовать функцию скользящего хэша, чтобы я мог взять хэши n-граммов очень большой строки.
Например:
"stackoverflow", разбитый на 5 граммов, будет:
"стек", "тако", "акков", "чкове",
"kover", "overf", "verfl", "erflo", "rflow"
Это идеально подходит для скользящей хеш-функции, потому что после того, как я вычислю первый х-грамм n-граммы, следующие сравнительно дешевы для вычисления, потому что мне просто нужно отбросить первую букву первого хэша и добавить новую последнюю букву второй хеш.
Я знаю, что в общем случае эта хеш-функция генерируется как:
H = c 1 a k - 1 + c 2 a k - 2 + c 3 a k - 3 + ... + c k a 0 , где a - константа, а c1, ..., ck - входные символы.
Если вы перейдете по этой ссылке в алгоритме поиска строки Рабина-Карпа , он скажет, что «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 в качестве прайма. Имеет ли значение, если мои хеши переполнятся? Я думаю, что это желательно, но я не уверен.
Похоже, это правильный путь?