一、什么是KMP匹配算法?和暴力算法有什么区别?
KMP算法是一种高效的匹配算法,牺牲了一定空间去保存NEXT数组,但是能够提升了我们的匹配效率。
暴力匹配主串指针需要回溯,KMP算法中主串指针不用回溯;
二、next数组是什么?如何实现?
当子串和主串不匹配的时候,值对应的索引的字符要移动到跟主串不匹配的字符对齐
实现:
公共前后缀:前面和后面是一样的;next = 公共前后缀 + 1;
三、图示next数组的实现
代码实现:
//next数组获取和输出
int * get_next(STRING* s){
//动态创建next数组的空间
int* next = (int*)malloc(sizeof(int)*(s->len+1));
next[0] = s->len;
int i = 1;//后缀
int j = 0;//前缀
next[1]=0;
while(i<=next[0]){
if(j==0 || s->data[i]==s->data[j]){
i++;
j++;
next[i]=j;
}else{
j = next[j];//前缀回溯
}
}
return next;
}
//输出
void printf_next(int* next){
for(int i=1;i<=next[0];i++){
printf("%d\t",next[i]);
}
printf("\n");
}
四、字符串结构体的创建,输入,输出代码(暴力匹配有)
#include <stdio.h>
#include <malloc.h>
//字符串结构体
typedef struct String{
char* data;
int len;
}STRING;
//初始化
STRING* init_string(void){
STRING* s = (STRING*)malloc(sizeof(STRING));
s->data = NULL;
s->len = 0;
return s;
}
//赋值
void get_string(STRING* s,char* data){
//先判断s的data是否有值,有就free掉
if(s->data==0){
free(s->data);
}
int len = 0;
char* temp = data; //传进来的字符串首地址;
//确定传进来的字符串除去/0的长度;
while(*temp != 0){
len++;
temp++;
}
if(len==0){
s->data = NULL;
s->len = 0;
}else{
s->len = len;
s->data = (char*)malloc(sizeof(char)*(len + 1));//字符串最后一个/0;
//给开辟的空间赋值;
for(int i=0;i<len;i++,data++){
s->data[i] = *data;
}
}
}
//输出
void printf_string(STRING* s){
for(int i=0;i<s->len;i++){
printf(i==0? "%c\t":"%c\t",s->data[i]);
}
printf("\n");
}
五、如何实现KMP匹配?
KMP匹配基本思路和暴力匹配差不多,唯一不同就是KMP匹配不需要回溯主指针,且子串指针也是回溯到j=next[j]的指定位置,而不是j=0;
代码实现:
//KMP匹配
void kmp_match(STRING* s,STRING* s1){
int* next = get_next(s1);
int i,j;
i=0;
j=0;
while(i<s->len&&j<s1->len){
if(s->data[i]==s1->data[j]){
i++;
j++;
}else{
j=next[j];
}
}
if(j==s1->len){
printf("匹配成功!\n");
}else{
printf("匹配失败!\n");
}
}
五、主函数代码和运行结果
int main(void){
STRING* s = init_string();
get_string(s,"ababa");
printf_string(s);
STRING* s1 = init_string();
get_string(s1,"abb");
printf_string(s1);
kmp_match(s,s1);
return 0;
}