簡體   English   中英

使用散列在另一個字符串中搜索子字符串

[英]Search for a substring in an another string using hashing

我編寫了代碼以使用散列在另一個字符串中查找子字符串,但它給了我錯誤的結果。

代碼工作原理的描述:

  1. p=31的前n冪存儲在數組pows
  2. 將每個子串s[0..i]哈希值存儲在數組h
  3. 使用h數組計算每個長度為 9 的子串的哈希值並將其存儲在一個集合中。
  4. 散列字符串t並存儲其散列值。
  5. 比較t哈希值和集合中的哈希值。

散列h[n2-1]應該存在於集合中,但它不存在。 你能幫我找出代碼中的錯誤嗎?

注意:當我使用模逆而不是乘以pows[i-8] ,代碼運行良好。


#include <bits/stdc++.h>

#define m 1000000007
#define N (int)2e6 + 3

using namespace std;

long long pows[N], h[N], h2[N];

set<int> ss;

int main() {

    string s = "www.cplusplus.com/forum";

    // powers array
    pows[0] = 1;
    int n = s.length(), p = 31;
    for (int i = 1; i < n; i++) {
        pows[i] = pows[i - 1] * p;
        pows[i] %= m;
    }

    // hash from 0 to i array
    h[0] = s[0] - 'a' + 1;
    for (int i = 1; i < n; i++) {
        h[i] = h[i - 1] + (s[i] - 'a' + 1) * pows[i];
        h[i] %= m;
    }

    // storing each hash with 9 characters in a set
    ss.insert(h[8]);
    for (int i = 9; i < n; i++) {
        int tp = h[i] - h[i - 9] * pows[i - 8];
        tp %= m;
        tp += m;
        tp %= m;
        ss.insert(tp);
    }

    // print hashes with 9 characters
    set<int>::iterator itr = ss.begin();
    while (itr != ss.end()) {
        cout << *(itr++) << " ";
    }
    cout << endl;

    // t is the string that i want to check if it is exist in s
    string t = "cplusplus";
    int n2 = t.length();
    h2[0] = t[0] - 'a' + 1;
    for (int i = 1; i < n2; i++) {
        h2[i] = h2[i - 1] + (t[i] - 'a' + 1) * pows[i];
        h2[i] %= m;
    }
    // print t hash
    cout << h2[n2 - 1] << endl;

    return 0;
}

我可以看到您的代碼有兩個問題:

  1. 當您計算長度為 9 的子字符串的哈希時,您將中間結果(類型為long long )存儲在一個int變量中。 這可能會導致整數溢出,並且您計算的哈希值可能不正確。
  2. 給定一個字符串s = {s[0], s[1], ..., s[n-1]} ,計算哈希的方法是: h = ∑ s[i] * p^i 在這種情況下,給定存儲在h的前綴哈希,子串s[l..r] (包括)的哈希應該是(h[r] - h[l - 1]) / p^(r-l+1) , 而不是你寫的。 這也是為什么使用模逆(需要在模下執行除法)是正確的。

我認為計算散列的更常見方法是相反的方法,即h = ∑ s[i] * p^(ni-1) 這允許您將子串哈希計算為h[r] - h[l - 1] * p^(r-l+1) ,這不需要計算模逆。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM