title: KMP
date: 2020-10-27 00:27:16
tags: [KMP, AL, C语言, 算法, 数据结构, DS]
categories: DSandAL
KMP算法,代码写的不好看,也不简洁,自己手敲的,也算是开天辟地了
后续持续优化代码 + 思路详细讲解,只希望让后来者少踩坑,起码不要踩我踩过的坑 T^T
先附上代码,后续更新详细讲解
非递归求next数组
// 开始手写KMP 自我感觉还是不太好的
// 串的底层用静态数组实现
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_SIZE 100
typedef unsigned char str[MAX_SIZE];
int getLength(str);
int* getNext(str);
int main(void)
{
str S = "dab5cdabcdabdebdedabcd1abdedabcd6abde";
str T = "dabcdabde";
int lengthT = getLength(T);
printf("%d\n", lengthT);
int lengthS = getLength(S);
printf("%d\n", lengthS);
int *next = getNext(T);
// 打印next数组
for (int i = 0; i < lengthT; i++)
printf("%d ", next[i]);
printf("\n");
int i, j = 0, flag = 0;
for (i = 0; i <= lengthS - lengthT;)
{
if (j == -1)
{
i++;
j++;
}
while (T[j] && (S[i] == T[j]))
{
i++;
j++;
}
if (j == lengthT)
{
flag = 1;
break;
}
j = next[j];
}
if (flag)
printf("%d", i - lengthT);
else
printf("找不到该子串\n");
return 0;
}
int getLength(str T)
{
int index = 0;
while (T[index++])
;
return index - 1;
}
int* getNext(str T)
{
int length = getLength(T);
int *next = (int *)malloc(sizeof(int) * length);
// next数组的前两个
next[0] = -1;
next[1] = 0;
for (int i = 2; i < length; i++)
{
// 当前字符的上一个字符的最大匹配数
int k = next[i - 1];
if (T[k] == T[i - 1])
next[i] = k + 1;
else
{
int flag = 1;
while (next[k] != -1)
{
k = next[k];
if (T[k] == T[i - 1])
{
next[i] = k + 1;
flag = 0;
break;
}
}
if (next[k] == -1 && flag)
next[i] = 0;
}
}
return next;
}
递归求next数组
递归中很多参数可以改成全局变量,本着把它封装成函数的目的,我没有设全局变量
确实挺浪费内存
// 手写KMP
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 100
// 定义字符串的数据类型
// 0号空间使用,配有长度
// 使用的是字符型指针,所以字符串的最后边不会被系统默认加上 '\0'
// 所以需要一个变量length来表示字符串的长度
typedef struct
{
char *str;
int length;
}String;
int *getNextArr(String);
// 需要原来的next数组, 目标字符串, 当前求到第几个字符的next域了
void getEachValue(String, int*, int, int);
int main(void)
{
String s, t;
// 在这里,直接让它指向那块不可被修改的字符串的内存了
// 后面还是有 '\0' 的
s.str = "dab5cdabcdabdebdedabcd1abdedabcd6abde";
s.length = strlen(s.str);
t.str = "dabcdabde";
t.length = strlen(t.str);
// 求next数组
int *next = getNextArr(t);
// 打印next数组
for (int i = 0; i < t.length; i++)
printf("%d ", next[i]);
printf("\n");
return 0;
}
int *getNextArr(String s)
{
int *next = (int *)malloc(sizeof(int) * s.length);
next[0] = -1;
next[1] = 0;
for (int i = 2; i < s.length; i++)
getEachValue(s, next, i - 1, i);
return next;
}
void getEachValue(String s, int *next, int p, const int index)
{
int k = next[p];
if (k == -1)
next[index] = 0;
else if (s.str[index - 1] == s.str[k])
next[index] = k + 1;
else
getEachValue(s, next, k, index);
}