prefix_table next 数组
GTGTGCF为例子,他的前缀表,前后缀相等的最大长度,不包含本身。
--------------------- -1
G----------------------0
GT---------------------0
GTG--------------------1
GTGT-------------------2
GTGTG------------------3
GTGTGC-----------------0
GTGTGCF-----------------0
整体后移一位
G-------------------- -1
GT---------------------0
GTG--------------------0
GTGT-------------------1
GTGTG------------------2
GTGTGC-----------------3
GTGTGCG----------------0
GTGTGCGF---------------0
得到前缀数组:
G T G T G C G F
-1 0 0 1 2 3 0 0
得到过程代码:
void prefix_table(char pattern[],int prefix[], int n){
prefix[0] = 0;
int len = 0, i = 1;
while(i < n){
if(pattern[i] == pattern[len]){
//prefix[i] = prefix[i-1]+1; //wrong
prefix[i] = ++len;
//len++;
i++;
}else{
if(len == 0){
prefix[i] = 0;
i++;
}
else len = prefix[len-1];
}
}
}
void move_prefix(int prefix[], int n){
for(int i = n-1; i > 0; i--){
prefix[i] = prefix[i-1];
}
prefix[0] = -1;
}
合并一下
void prefix_next(char pattern[], int prefix[], int n){
prefix[0] = -1;
prefix[1] = 0;
int i = 2,len = 0;
while(i < n){
if(pattern[i-1] == pattern[len]){
prefix[i] = ++len;
i++;
}else{
if(len >= 0) len = prefix[len];
else{
prefix[i++] = 0;
len++;
}
}
}
}
查找过程:
定义被查找串txt, 长度m, 查找串pattern, 长度n , 两个指针 i , j 分别指向 两个串。
如果相等,两个指针都后移,如果不相等,那么j = prefix[j]
void kmp_search(char text[], char pattern[]){
int m = strlen(text);
int n = strlen(pattern);
int * prefix = malloc(sizeof(int)*n);
prefix_next(pattern, prefix, n);
int i = 0, j= 0;
while(i < m){
if(j == n-1 && text[i] == pattern[j]){
printf("Fount at %d", i-j);
j = prefix[j];
i++;
}
if(text[i] == pattern[j]){
i++; j++;
}else {
j = prefix[j];
if(j == -1){
i++; j++;
}
}
}
}