Рабин-Карп: вычисление скользящего хеша добавляет большое простое число к ранее вычисленному хешу

Я думаю, что концептуально понимаю алгоритм сопоставления с образцом RabinKarp с использованием скользящего хеша. Просматривая пример реализации здесь, я обнаружил, что большое простое число число q добавляется к ранее вычисленному скользящему хешу.

for (int i = m; i < n; i++) {
            // Remove leading digit, add trailing digit, check for match. 
            txtHash = (txtHash + q - RM*txt.charAt(i-m) % q) % q; //Why +q here?
            txtHash = (txtHash*R + txt.charAt(i)) % q; 

            // match
            int offset = i - m + 1;
            if ((patHash == txtHash) && check(txt, offset))
                return offset;
        }

Я не уверен, зачем это нужно. Могу я получить помощь с этим?

В моем ограниченном тестировании я получаю тот же результат независимо от того, включен ли q термин.

Связано ли это с тем, какая версия алгоритма (Монте-Карло / Лас-Вегас) реализуется?


person bp4D    schedule 22.05.2019    source источник
comment
+ q мне тоже кажется ошибкой, чего бы это ни стоило.   -  person 500 - Internal Server Error    schedule 22.05.2019
comment
@ 500-InternalServerError Спасибо! Не могли бы вы также пролить свет на то, почему мы получаем правильный результат при включении +q?   -  person bp4D    schedule 22.05.2019


Ответы (1)


Термин +q используется, чтобы избежать работы с отрицательными числами.

Мы хотим, чтобы txtHash всегда лежал в интервале [0;q[, без этого +q он также мог бы находиться в ]-q;0[.

Это могло привести к потере рисунка. например, если patHash = 0xdead, но вы вычисляете txtHash = -q+0xdead. Эти два значения равны математически mod q, но различаются для Java, взятой % q.

person One Lyner    schedule 27.06.2019
comment
если я запущу алгоритм без + q, он все равно будет работать. Причина, по которой я спрашиваю, заключается в том, что я только что узнал, что -3% 7 = 4% 7 = 4, поэтому наличие отрицательного промежуточного хеша не будет иметь никаких побочных эффектов, пока есть модуль q. - person bp4D; 30.04.2020
comment
% в Java - это не оператор по модулю, а остаток docs.oracle.com/javase/specs/jls/se8/html/. Таким образом, в Java -3%7=-3; 4%7=4 и, конечно же, -3 != 4. См., Например, programming.guide/java/ - person One Lyner; 30.04.2020
comment
Спасибо, что осветили это для меня. Думаю, теперь я понимаю общую идею, но мне все еще трудно понять точную математику. - person bp4D; 30.04.2020