详细算法描述见《算法导论32.4》,以下是C实现:
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- //预处理:所需时间为O(m),空间O(m)
- void compute_prefix_func(char sp[], int p[])
- {
- int m, k, q;
- m = strlen(sp);
- p[0] = 0;
- k = 0;
- for (q = 1; q < m; q++) {
- while ((k > 0) && (sp[k] != sp[q])) {
- k = p[k-1];
- }
- if (sp[k] == sp[q])
- k++;
- p[q] = k;
- }
- for (q = 0; q < m; q++)
- printf("p[%d] = %d\n", q, p[q]);
- }
- //匹配:所需时间为O(n)
- void kmp_matcher(char st[], char sp[])
- {
- int n, m, q, i;
- int *p;
- n = strlen(st);
- m = strlen(sp);
- p = (int *)malloc(sizeof(int) * m);
- compute_prefix_func(sp, p);
- q = 0; //Number of characters matched
- for (i = 0; i < n; i++) {
- while ((q > 0) && (sp[q] != st[i])) {
- q = p[q-1]; //Next character does not match
- }
- if (sp[q] == st[i]) //Next character matches
- q++;
- if (q == m) { //Is all of P matched?
- printf("Pattern occurs with shift %d\n", i - (m - 1));
- q = p[q-1]; //Look for the next match
- }
- }
- free(p);
- }
- int main(void)
- {
- char st[] = "abcdabcabcabcabcdabcabcdabcabcabcd";
- char sp[] = "abcabcd";
- kmp_matcher(st, sp);
- return 1;
- }
KMP算法详解