KMP 算法是对于暴力匹配算法的改进
next 数组
* 暴力在刚在的匹配的过程中,主串指针回溯了多次,才达到了匹配的状态
* KMP算法,主串没有回溯,并且快速达到匹配状态。
* KMP算法是一种高效的模式匹配算法,它牺牲了一定的空间保存 next 数组,提高了匹配效率
* KMP算法可以更加智能的移动字符串,让字符串达到匹配状态
next 数组
* 当该字符与主串发生不匹配之后,值对应索引的字符要移动到跟主串不匹配字符对齐。
* 算法:公共前后缀
* 前面和后面是一样的
* next值 = 公共前后缀 + 1
* 找公共前后缀的目的是:为了找到前后能够匹配的状态
KMP算法的核心:减少主串指针的移动,并且快速找到前后匹配的状态,从而加快我们匹配的进程
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct String
{
char *data;
int len;
} String;
String *initString()
{
String *string = (String *)malloc(sizeof(String));
if (string == NULL)
{
printf("malloc string error\n");
exit(1);
}
string->data = NULL;
string->len = 0;
return string;
}
void stringAssign(String *string, char *data)
{
if (string->data != NULL)
{
free(string->data);
string->data = NULL;
}
int len = 0;
char *temp = data;
while (*temp) // 记录长度
{
len++;
temp++;
}
if (len == 0)
{
string->data = NULL;
string->len = 0;
}
else
{
temp = data; // 重新置位temp
string->len = len;
string->data = (char *)malloc(sizeof(char) * (len + 1)); // 给string->data 在堆上分配空间
if (string->data == NULL)
{
printf("malloc string—>data error\n");
exit(1);
}
for (int i = 0; i < len; i++)
{
string->data[i] = *temp;
temp++;
}
}
}
void printString(String *string)
{
for (int i = 0; i < string->len; i++)
{
if (i == 0)
{
printf("%c ", string->data[i]);
}
else
{
printf(" -> %c ", string->data[i]);
}
}
printf("\n");
}
int *getNext(String *string)
{
int *next = (int *)malloc(sizeof(int) * string->len);
if (next == NULL)
{
printf("malloc next error!");
exit(1);
}
int i = 0; // 表示字符串的索引
int j = -1; // next 的初始值
next[i] = j;
while (i < string->len - 1)
{
if (j == -1 || string->data[i] == string->data[j])
{
i++;
j++;
next[i] = j;
}
else
{
j = next[j];
}
}
return next;
}
void KMPMatch(String *master, String *sub, int *next)
{
int i = 0;
int j = 0;
while (i < master->len && j < sub->len)
{
if (j == -1 || master->data[i] == sub->data[j])
{
i++;
j++;
}
else
{
j = next[j];
}
}
if (j == sub->len)
{
printf("KMP 匹配成功!\n");
}
else
{
printf("KMP 匹配失败!\n");
}
}
void printNext(int *next, int len)
{
printf("next > ");
for (int i = 0; i < len; i++)
{
if (i == 0)
{
printf("%d", next[i] + 1);
}
else
{
printf(" -> %d ", next[i] + 1);
}
}
printf("\n");
}
int main()
{
String *stringmaster = initString();
stringAssign(stringmaster, "hello world");
printString(stringmaster);
printf("----------------------------------------------------------\n");
int *next = getNext(stringmaster);
printNext(next, stringmaster->len);
printf("----------------------------------------------------------\n");
String *stringsub = initString();
stringAssign(stringsub, "llo");
printString(stringsub);
printf("----------------------------------------------------------\n");
KMPMatch(stringmaster, stringsub, next);
return 0;
}
执行结果:
superlan@GodFather:~/C_Language/data_structure$ ./a.out
h -> e -> l -> l -> o -> -> w -> o -> r -> l -> d
----------------------------------------------------------
next > 0 -> 1 -> 1 -> 1 -> 1 -> 1 -> 1 -> 1 -> 1 -> 1 -> 1
----------------------------------------------------------
l -> l -> o
----------------------------------------------------------
KMP 匹配成功!