Rabin-Karp算法代码中的负哈希值

Posted

技术标签:

【中文标题】Rabin-Karp算法代码中的负哈希值【英文标题】:Negative hash value in code of Rabin-Karp Algorithm 【发布时间】:2021-05-26 11:50:44 【问题描述】:

我从这个网站了解 Rabin-Karp 算法:https://www.geeksforgeeks.org/rabin-karp-algorithm-for-pattern-searching/

他们为算法编写了以下 C++ 代码:

#include <bits/stdc++.h> 
using namespace std; 
  
// d is the number of characters in the input alphabet  
#define d 256  
  
/* pat -> pattern  
    txt -> text  
    q -> A prime number  
*/
void search(char pat[], char txt[], int q)  
  
    int M = strlen(pat);  
    int N = strlen(txt);  
    int i, j;  
    int p = 0; // hash value for pattern  
    int t = 0; // hash value for txt  
    int h = 1;  
  
    // The value of h would be "pow(d, M-1)%q"  
    for (i = 0; i < M - 1; i++)  
        h = (h * d) % q;  
  
    // Calculate the hash value of pattern and first  
    // window of text  
    for (i = 0; i < M; i++)  
      
        p = (d * p + pat[i]) % q;  
        t = (d * t + txt[i]) % q;  
      
  
    // Slide the pattern over text one by one  
    for (i = 0; i <= N - M; i++)  
      
  
        // Check the hash values of current window of text  
        // and pattern. If the hash values match then only  
        // check for characters on by one  
        if ( p == t )  
          
            /* Check for characters one by one */
            for (j = 0; j < M; j++)  
              
                if (txt[i+j] != pat[j])  
                    break;  
              
  
            // if p == t and pat[0...M-1] = txt[i, i+1, ...i+M-1]  
            if (j == M)  
                cout<<"Pattern found at index "<< i<<endl;  
          
  
        // Calculate hash value for next window of text: Remove  
        // leading digit, add trailing digit  
        if ( i < N-M )  
          
            t = (d*(t - txt[i]*h) + txt[i+M])%q;  
  
            // We might get negative value of t, converting it  
            // to positive  
            if (t < 0)  
            t = (t + q);  
          
      
  
  
/* Driver code */
int main()  
  
    char txt[] = "GEEKS FOR GEEKS";  
    char pat[] = "GEEK"; 
        
      // A prime number  
    int q = 101;  
      
      // Function Call 
      search(pat, txt, q);  
    return 0;  
  

我不明白的是这段代码:

            // We might get negative value of t, converting it  
            // to positive  
            if (t < 0)  
            t = (t + q);  

t 怎么可能是负面的?我们从t 中减去的总是小于t,然后我们向它添加一些东西,那么t 的可能性是从哪里来的呢?

我在没有if 语句的情况下测试了代码,但它不能正常工作。预期的输出是:

Pattern found at index 0
Pattern found at index 10

但我得到了:

Pattern found at index 0

【问题讨论】:

忘记那个网站。它演示了如何编写C++代码,与专业编程无关。 Why should I not #include &lt;bits/stdc++.h&gt;?Why is using namespace std; considered bad practice? 也许缩进第二行代码会更清晰?为什么t 不应该是负数?您还可以在该行中设置断点以查看它何时被触发。 ***.com/questions/7594508/… 【参考方案1】:

Aki Suihkonen 有它;模数为正时,结果要么为零,要么与被除数符号相同,而 Rabin--Karp 假设结果始终为非负数。

例如,如果我们这样做

t = 3
t = (t + 5) % 7
t = (t - 5) % 7

那么值是

(3 + 5) % 7 == 1
(1 - 5) % 7 == -4

如果我们加 7,就可以得到 3。

【讨论】:

以上是关于Rabin-Karp算法代码中的负哈希值的主要内容,如果未能解决你的问题,请参考以下文章

模式匹配:滚动哈希到 Rabin-Karp 算法

在 rabin-karp 滚动哈希中选择基数和模素数

C ++的“map”容器是否对字符串的连续子串应用Rabin-Karp算法?

算法哈希表 ( 两数之和 )

算法导论字符串匹配—朴素算法Rabin-Karp有限自动机KMP

人工智能算法之哈希算法