KMP算法
KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。
已经匹配过的字符中,相同的前后缀是不需要二次匹配的,因而可以跳过。
计算
计算模式串回溯时需要跳过的字符数,即已匹配的字符相同前后缀的长度
void get_next(char *T, int *next)
{
int i, j;
i = 1;
j = 0; // j 表示相同前后缀长度
next[0] = 0;
while ( i < strlen(T)) {
if (T[i] == T[j]) {
++ j;
next[i] = j; // 相同前后缀长度为几就跳过几个字符
++ i;
} else {
if (j == 0) {
next[i] = 0;
i ++;
}
else
j = next[j-1];
}
}
}
匹配
主串下标不回溯
int KMP (char *S, char *T, int pos)
{
int i = pos; // 匹配初始位置
int j = 0; // 模式串中匹配元素位置
int lenS = strlen(S);
int lenT = strlen(T);
int next[lenT];
get_next(T, next);
while (i < lenS && j < lenT) {
if (j == 0 || S[i] == T[j]) {
i ++;
j ++;
} else {
j = next[j-1];
}
}
if ( j > lenT - 1 )
return i - lenT;
else
return 0;
}
测试
int main()
{
char *A = "abcfagdafafdafdadsaasf";
// char *B = "abcabx";
// char *B = "aaaaax";
// char *B = "gdafaf";
char *B = "ababaaaba";
int L[strlen(B)];
get_next(B, L);
for (int i=0; i < strlen(B); i ++)
printf("%d\t", L[i]);
printf("\n%d", KMP(A, B, 0));
return 0;
}