关于KMP算法(看毛片算法),自己刚开始学习的时候一直不理解。主演是算法中的回溯部分。至于KMP算法原理我这里就不重复讲解了,网上有大量的讲解。而我认为KMP算法的核心就是理解它的回溯原理。首先是字串本身的回溯,即求next数组。而我之前一直不理解的一句算法就是下面代码中标记红色的部分。之前的疑问就是,既然T[i]!=T[j],那么为什么不从j-1处比较。现在想想当时的想法是错误的,如果从j-1处比较,那么还需要继续遍历其他的值,才能得出next的值。这无疑类似于BF算法了。效率不高,而代码中红色的部分就是通过回溯,使j的值回溯到上一次匹配的值,这样前面的部分就不要比较,自然是相等的了。只要比较后面的值,以此类推继续得出next的值。
void GetNext (int *next, char *T){ int i, j; i = 0; j = -1; next[i] = j; while(i < strlen(T)-1) { if(j == -1 || T[i] == T[j]) { i++; j++; next[i] = j; } else {
j = next[j]; } }}
KMP算法跟next的过程类似,下面使完整代码
#include <stdio.h>#include <string.h>void GetNext (int *next, char *T){ int i, j; i = 0; j = -1; next[i] = j; while(i < strlen(T)-1) { if(j == -1 || T[i] == T[j]) { i++; j++; next[i] = j; } else { j = next[j]; } }}int KMP (char *S, char *T){ int i, j, next[255]; i = 0; j = 0; GetNext(next, T); while(i < strlen(S)) { if(j == -1 || S[i] == T[j]) { i++; j++; } else { j = next[j]; } if(j == strlen(T)) { return i-strlen(T); } } return 0;}int main (){ char S[100], T[100]; int pos, next[255]; gets(S); gets(T); pos = KMP(S, T); printf("%d\n", pos); return 0;}
KMP算法改进,即next数组的改进:
#include <stdio.h>
#include <string.h>
void GetNext (int *next, char *T)
{
int i, j;
i = 0;
j = -1;
next[i] = j;
while(i < strlen(T)-1)
{
if(j == -1 || T[i] == T[j])
{
i++;
j++;
if(T[i] != T[j])
next[i] = j;
else
next[i] = next[j];
}
else
{
j = next[j];
}
}
}
int KMP (char *S, char *T)
{
int i, j, next[255];
i = 0;
j = 0;
GetNext(next, T);
while(i < strlen(S))
{
if(j == -1 || S[i] == T[j])
{
i++;
j++;
}
else
{
j = next[j];
}
if(j == strlen(T))
{
return i-strlen(T);
}
}
return 0;
}
int main ()
{
char S[100], T[100];
int pos, next[255];
gets(S);
gets(T);
pos = KMP(S, T);
printf("%d\n", pos);
return 0;
}
博客链接:
https://blog.csdn.net/hackbuteer1/article/details/7319115