我必须实现Rabin-Karp字符串搜索算法。
我认为我的rkhash_next
功能有问题。我的教授告诉我们使用以下公式计算字符串中的下一个哈希值:
yi+1 = 256^m-1*Y[i+1] + 256^m-2*Y[i+2] + ... + Y[i+m]
= 256 * ( 256^m-2*Y[i+1] + ... Y[i+m-1]) + Y[i+m]
= 256 * ((256^m-1*Y[i] + 256^m-2*Y[i+1] + ... Y[i+m-1]) - 256^m-1*Y[i]) + Y[i+m]
= 256 * ( yi - 256^m-1 * Y[i]) + Y[i+m]
= 256 * yi - 256^m * Y[i] + Y[i+m]
我做到了这一点,但是我的程序不断给出令人惊讶的哈希值,因为它“滚动”了字符串。以下是我的rkhash_substring_match
的一般代码:
int rk_substring_match(const char *pattern, const char *doc, int *first_match_ind)
{
int plength = strlen(pattern);
int dlength = strlen(doc);
int i,j,x;
int counter = 0;
int first_match = 0;
first_match_ind = &first_match;
long long hash = 256;
long long *h;
long long phash = 0;
long long dhash = 0;
for (x = 0; x <= plength-1; x++)
hash *= 256;
phash = rkhash_init(pattern, plength,h);
dhash = rkhash_init(doc, plength,h);
for(i = 0; i <= dlength - plength; i++) {
if (phash == dhash) {
for (j = 0; j < plength; j++)
if (doc[i+j] != pattern[j])
break;
if (j == plength && counter == 0)
first_match = i;
if (j == plength)
counter++;
}
printf("%lld\n", dhash);
dhash = rkhash_next(dhash,hash,doc[i + 1], doc[i+plength]);
}
return counter;
}
在我的课程中,long long变量用于存储哈希值,256 ^ m用于以后在程序中使用。下面是rkhash_init,它生成哈希值并在h:
的值中存储256 ^ m long long rkhash_init(const char *charbuf, int m, long long *h)
{
int i,j;
long long value = 1;
long long hash = 0;
for (j = 0; j < m; j++)
value *= 256;
h = &value;
long long val = value;
for (i = 0; i < m -1 ; i++) {
value = value/256;
hash += mmul(value, charbuf[i]);
}
hash += charbuf[m-1];
return hash;
}
这是问题孩子,rkhash_next:
long long rkhash_next(long long curr_hash, long long h, char leftmost, char rightmost)
{
return madd(msub(mmul(curr_hash, 256), mmul(leftmost, h)), rightmost);
}
madd,msub和mmul是教授给我们的功能。它们在完成加法,减法或乘法之后执行模运算。例如,这是madd函数:
long long madd(long long a, long long b)
{
return (a + b) % PRIME;
}
任何人都可以帮我找出我的程序无效的原因!?