Rabin-Karp子串搜索算法结果异常,rkhash_next函数排查求助
rkhash_next Function Hey there! Let’s break down why your rkhash_next might be failing even though you followed the given formula. I’ve debugged my share of Rabin-Karp hash issues before, so here are the most common pitfalls to check:
1. Unhandled Integer Overflow (and Missing Modulo Operations)
The formula you’re using involves large powers of 256—even for small m, 256^m can quickly exceed the limits of standard integer types. Rabin-Karp relies on modulo arithmetic to keep numbers manageable, and skipping it at any step will throw off your hashes.
Your formula should be adjusted to include modulo at every stage (using a large prime mod_value like 10^9+7 or 911382629):
y[i+1] = (256 * (y[i] - (256^m * Y[i]) % mod_value) + Y[i+m]) % mod_value
Also, if (y[i] - (256^m * Y[i])) results in a negative number, you need to add mod_value before taking the final modulo to avoid negative hash values.
2. Incorrect Precomputation of 256^m
Double-check that you’re precomputing 256^m mod mod_value correctly, not 256^(m-1) or another exponent. A common mistake is miscalculating this power—use a loop or built-in modular exponentiation to avoid overflow during precomputation.
For example, in C:
unsigned long long compute_base_pow_m(int m, unsigned long long mod_value) { unsigned long long result = 1; for (int i = 0; i < m; i++) { result = (result * 256) % mod_value; } return result; }
3. Indexing Mix-Ups (Zero vs. One-Based)
It’s easy to mix up which characters correspond to Y[i] and Y[i+m]. Make sure:
Y[i]is the first character of the current window (the one being dropped)Y[i+m]is the new character entering the next window
If your initial hash uses zero-based indexing for the first m characters, your rkhash_next function must follow the same convention.
4. Mismatched Initial Hash Calculation
If your initial window hash (y[i]) is computed incorrectly, every subsequent rkhash_next result will be wrong. Verify that your initial hash matches the formula:
y[0] = (256^(m-1)*Y[0] + 256^(m-2)*Y[1] + ... + Y[m-1]) % mod_value
A safer way to compute this iteratively (avoiding large exponents) is:
unsigned long long compute_initial_hash(unsigned char* Y, int m, unsigned long long mod_value) { unsigned long long hash = 0; for (int i = 0; i < m; i++) { hash = (hash * 256 + Y[i]) % mod_value; } return hash; }
5. Character Value Conversion Errors
Ensure that Y contains the correct numeric values for each character. For 256-base hashing, you should use the full ASCII value of each character (0-255). If you’re accidentally subtracting an offset (like 'a' for lowercase letters) or using a non-ASCII encoding, your hash calculations will be off.
Test with a Small Example
To isolate the issue, test with a tiny input:
- Let
m=2, text ="ABAC"(Y = [65, 66, 65, 67]) - Initial hash:
(65*256 + 66) % mod_value = 16706 - Next hash should be
(66*256 + 65) % mod_value = 16961
Plug these values into your rkhash_next function—if it doesn’t return 16961, you’ll know exactly where the calculation breaks.
内容的提问来源于stack exchange,提问作者baldwin

