#define MAX_NUM 100
void kmpNext(const char pattern[], int pattern_len, int next[])
{
int i, j;
next[0] = -1;
//超级关键的初始化~
i = 0;
j = -1;
while (i < pattern_len)
{
//i是后缀结尾,j是前缀结尾
//先找匹配项,然后自增,来判断当前项的next
//以往的思路都是通过前next直接求当前
//但有一个bug是我们每次都必须找匹配
//这样子做完全做到了
//j==-1是个特例,只需判断和字符串首的情况即可
if (j == -1 || pattern[i] == pattern[j])
{
i++;
j++;
if (i >= pattern_len)
break;
if (pattern[i] == pattern[j])
next[i] = next[j];
else
next[i] = j ;
}
else
j = next[j];
}
}
int kmp(const char str[], int str_len, const char pattern[], int pattern_len)
{
int i, j;
int next[MAX_NUM];
kmpNext(pattern, pattern_len, next);
i = j = 0;
while (i < str_len - pattern_len && j < pattern_len)
{
if (str[i] == pattern[j])
{
i++;
j++;
}
else
{
if (next[j] == -1)
{
j = 0;
i++;
}
else
j = next[j];
}
}
if (j < pattern_len)
return -1;
else
return i - pattern_len + 1;
}
这次的思路是正确的..
next[i]表示i之前的字符串满足前缀/后缀组合的最大长度,也就是我们下次进行比对匹配的位置(因为前缀从0开始,所以长度即为下标)
而在next的循环中,不变式为"以j-1为结尾的前缀同以i-1结尾的后缀是匹配的(j=-1时为特例,表示开始)",所以当j/i匹配时,我们就可以直接计算i+1对对应的next值了.
这个和以前的思路不同..以前是试图通过i-1来计算i,而现在是得到i,然后求i+1..这个思路明显很高明