Соответствие строк Рабина-Карпа не соответствует
Я работал над функцией соответствия строк Рабина-Карпа в C++, и я не получаю никаких результатов. У меня такое чувство, что я неправильно вычисляю некоторые значения, но я не знаю, какие из них.
Прототип
void rabinKarp(string sequence, string pattern, int d, int q);
Реализация функции
void rabinKarp(string sequence, string pattern, int d, int q)
{
//d is the |∑|
//q is the prime number to use to lessen spurious hits
int n = sequence.length(); //Length of the sequence
int m = pattern.length(); //Length of the pattern
double temp = static_cast<double> (m - 1.0);
double temp2 = pow(static_cast<double> (d), temp); //Exponentiate d
int h = (static_cast<int>(temp2)) % q; //High Order Position of an m-digit window
int p = 0; //Pattern decimal value
int t = 0; //Substring decimal value
for (int i = 1; i < m; i++) { //Preprocessing
p = (d*p + (static_cast<int>(pattern[i]) - 48)) % q;
t = (d*t + (static_cast<int>(sequence[i])-48)) % q;
}
for (int s = 0; s < (n-m); s++) { //Matching(Iterate through all possible shifts)
if (p == t) {
for (int j = 0; j < m; j++) {
if (pattern[j] == sequence[s+j]) {
cout << "Pattern occurs with shift: " << s << endl;
}
}
}
if (s < (n-m)) {
t = (d*(t - ((static_cast<int>(sequence[s+1]) - 48)*h)) + (static_cast<int>(sequence[s + m + 1]) - 48)) % q;
}
}
return;
}
В моем вызове функции я передаю 2359023141526739921 как последовательность, 31415 как образец, 10 как основание и 13 как простое число. Я ожидаю, что будет одно фактическое совпадение и одно ложное совпадение, но я никогда не получу оператор вывода из соответствующей части функции. Что я делаю неправильно?
Заранее спасибо, Мэдисон
2 ответа
Большой недостаток в кодировании Rabin Karp - это оператор по модулю. Когда два числа X и Y совпадают по модулю Q, тогда (X% Q) должно быть равно (Y% Q), но на используемом компиляторе C++ они будут равны, только если X и Y оба положительные или оба отрицательные. Если X положительный, а Y отрицательный, то (X% Q) будет положительным, а (Y% Q) отрицательным. На самом деле (X % Q)-Q == (Y % Q) в этом случае.
Обходной путь - проверять наличие отрицательных значений после каждого по модулю, и если есть какие-либо, чтобы добавить q к переменной, то ваш цикл предварительной обработки становится:
p = (d*p + pattern[i]) % q;
if ( p < 0 ) p += q;
t = (d*t + sequence[i]) % q;
if ( t < 0 ) t += q;
В главном цикле необходимо добавить аналогичную проверку.
Если вы не переопределены ^
это вычисление xor, а не возведение в степень. Кроме того, вы должны быть осторожны с переполнением максимального значения int
прежде чем выполнять %
,