KMP算法和代码解析
1.KMP算法的思想
KMP应用在字符串匹配上,和暴力匹配的最大改进就是找到一个最合适的位置进行“回溯”。
首先求要匹配字符串的前缀和后缀,再得到“next数组”(用于找回溯的位置)。然后利用这个“next数组”进行匹配。
2.代码
咱们直接上代码
void make_next(const char *pattern,int *next){
int q = 1, k = 0;
int m = strlen(pattern);
next[0] = 0;
for(q = 1,k = 0;q < m;q++){
while(pattern[q] != pattern[k] && k > 0){
k = next[k-1];
}
if(pattern[q] == pattern[k]){
k++;
}
next[q] = k;
}
}
这一段代码就是构造“next数组”,开始需要指定next[0]=0。每一次循环中,k指向pattern的第0个位置,q指向pattern的最后一个位置,如果k和q对应的元素相同,则使k+1;反之k等于next数组中位置为k-1的元素的值。之后进行字符串匹配。
int kmp(const char *text, const char *pattern, int *next){
int n = strlen(text);
int m = strlen(pattern);
int i,q;
make_next(pattern,next);
for(i = 0,q = 0;i < n;i++){
while(text[i] != pattern[q] && q > 0){
q = next[q - 1];
}
if(text[i] == pattern[q]){
q++;
}
if(q == m){
return i - q + 1;
}
}
}
大致的思路和构造“next数组”的方法一致,i指向text(要匹配的全文)的第0个位置,q指向pattern的第0个位置。利用构造的“next数组”,i和q指向的值相同,则使q加一;反之回溯到"next数组”在q-1位置的值。完成匹配后返回匹配到的第一个字符的位置。
main()函数为:
int main()
{
char *text = "abcabcabcabcabcd";
char *pattern = "abcabcd";
int next[20] = {0};
int idx = kmp(text, pattern, next);
printf("match pattern: %d\n", idx);
}
希望可以让读者能弄懂KMP的思路和具体代码编写。