我一直在使用C ++中的Rabin-Karp字符串匹配函数,但我没有得到任何结果。我有一种感觉,我没有正确计算一些值,但我不知道哪一个。
原型
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作为素数。我希望有一个实际匹配和一个虚假命中,但我从来没有从函数的匹配部分获得输出语句。我做错了什么?
先谢谢麦迪逊
答案 0 :(得分:8)
编码Rabin Karp的重要问题是modulo operator。当两个数字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;
主循环中的t需要添加类似的检查。
答案 1 :(得分:5)
除非你重新定义^
,否则它是计算xor,而不是取幂。此外,在执行int
之前,您应该注意溢出%
的最大值。