看了网上很多关于KMP算法的资料,感觉还是有些迷惑,仔细分析下原理,其实就是子串的模式匹配问题。模式匹配后得到的值就是next数组。next数组的求解过程既是模式匹配的过程。
例如字符串“abcabcacab”进行模式匹配后得到的next数组为:
i 0 1 2 3 4 5 6 7 8 9
pattern a b c a b c a c a b
next[i] -1 0 0 0 1 2 3 4 0 1
子串的模式匹配值next[i]可以通过下面的数学公式获得:
上面的表就是根据上面的公式获得的,例如next[7] =4,就是pattern[0]pattern[1]pattern[2]pattern[3] =pattern[3]
pattern[4]pattern[5]pattern[6],所以k - 1 = 3故next[7] = 4.next[0] = -1是规定的,next[1] = 0是因为找不到上述公式中那样的k满足等式的条件故等于0,其他同理.
通过上面的分析,即可以根据公式编程:
#include<stdio.h>
#include "string.h"
#include "malloc.h"
void get_next(char *pattern, int *next)
{
int i = -1; //前缀索引
int j = 0; //后缀索引
int p_len = strlen(pattern); //获得字符串的长度
next[0] = -1;
while (j < p_len - 1) //注意是p_len - 1
{
if (-1 == i || pattern[j] == pattern[i])
{
i++;
j++;
next[j] = i;
}
else
{
i = next[i];
}
}
}
int KMP(char* target, char* pattern)
{
int p_len = strlen(pattern);
int t_len = strlen(target);
int p_index = -1;
int t_index = -1;
int *next = (int*)malloc(sizeof(int)*p_len);
get_next(pattern, next);
while (t_index < t_len && p_index < p_len)
{
if (-1 == p_index || pattern[p_index] == target[t_index])
{
t_index++;
p_index++;
}
else
{
p_index = next[p_index];
}
}
free(next);
return (p_len == p_index ? t_index - p_len : -1);
}
int main(void)
{
char target[] = "babcbabcabcaabcabcabcacabc";
char pattern[] = "abcabcacab";
int index = KMP(target, pattern);
printf("index = %d", index);
return 0;
}