写在前面:
模式串下标从0开始,next数组和nextval数组从-1开始;
例如:
abcabd aaaaaaab
next -100012 -10123456
nextval -100002 -10000006
代码:
普通KMP (时间复杂度 O(n + m))
#include <stdio.h> #include <string.h> #define N 100 void Get_Next(char t[], int len); int KMP(char s[], char t[], int lens, int lent); int next[N]; int main() { char s[N], t[N]; scanf("%s%s", s, t); Get_Next(t, strlen(t)); int start = KMP(s, t, strlen(s), strlen(t)); printf("%d\n", start); return 0; } int KMP(char s[], char t[], int lens, int lent) { int i = 0, j = 0; while(i < lens && j < lent){ if(j == 0 || s[i] == t[j]){ //虽然next是从-1开始,但这儿j最小为0 i ++; j ++; } else{ j = next[j]; } } if(j == lent) return i - lent; else return -1; } void Get_Next(char t[], int len) { int i = 0, j = -1; next[0] = -1; while(i < len){ if(j == -1 || t[i] == t[j]){ /* j == -1 表示当前next[i]保持初始值(0)不变,然后next[i+1] = 0; next[i] = j 指 t[i-j+1...i-1] == t[0...j]; */ i ++; j ++; next[i] = j; } else j = next[j]; } }
#include <stdio.h> #include <string.h> #define N 100 void Get_NextVal(char t[], int len); int KMP(char s[], char t[], int lens, int lent); int nextval[N]; int main() { char s[N], t[N]; scanf("%s%s", s, t); Get_NextVal(t, strlen(t)); int start = KMP(s, t, strlen(s), strlen(t)); printf("%d\n", start); return 0; } int KMP(char s[], char t[], int lens, int lent) { int i = 0, j = 0; while(i < lens && j < lent){ if(j == 0 || s[i] == t[j]){ i ++; j ++; } else{ j = nextval[j]; } } if(j == lent) return i - lent; else return -1; } void Get_NextVal(char t[], int len) { int i = 0, j = -1; nextval[0] = -1; while(i < len){ if(j == -1 || t[i] == t[j]){ i ++; j ++; if(t[i] != t[j]) nextval[i] = j; else nextval[i] = nextval[j]; } else j = nextval[j]; } }