代码实现了 KMP(Knuth-Morris-Pratt)字符串匹配算法,用于在主串中查找模式串的位置。具体步骤如下:
1、输入部分:提示用户输入主串和模式串,并计算它们的长度。
2、计算 next 数组:调用 GetNext 函数计算模式串的 next 数组,该数组用于在匹配过程中避免不必要的回溯。
3、字符串匹配:调用 IndexKMP 函数在主串中查找模式串的位置,并输出结果。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSTRLEN 64
// 函数声明
int GetNext(char T[MAXSTRLEN], size_t next[MAXSTRLEN]);
int IndexKMP(char S[MAXSTRLEN], char T[MAXSTRLEN], size_t next[MAXSTRLEN], size_t pos);
int main()
{
size_t index, N, M;
size_t next[MAXSTRLEN] = {0};// 用于存储 next 数组,初始化为 0
char s[MAXSTRLEN];// 定义主串 s
char t[MAXSTRLEN];// 定义模式串 t
printf("输入主串 s:");
fgets(s, MAXSTRLEN, stdin);
s[strcspn(s, "\n")] = 0;
printf("输入模式串 t:");
fgets(t, MAXSTRLEN, stdin);// 使用 fgets 函数读取用户输入的模式串 t
t[strcspn(t, "\n")] = 0;// 去除 fgets 可能读取的换行符
N = strlen(s);// 计算主串 s 的长度
M = strlen(t);// 计算模式串 t 的长度
printf("主串 s 长 = %d\n", N);
printf("模式串 t 长 = %d\n", M);
GetNext(t, next);// 调用 GetNext 函数计算模式串 t 的 next 数组
index = IndexKMP(s, t, next, 1);// 调用 IndexKMP 函数在主串 s 中查找模式串 t 的位置
if (index > 0)
{
printf("模式串在主串的位置从第 %d 个字符开始\n", index);// 如果找到模式串,输出其在主串中的起始位置
} else {
printf("主串 s 中不含模式串 t\n");
}
return 0;
}
// 计算模式串 T 的 next 数组
int GetNext(char T[MAXSTRLEN], size_t next[MAXSTRLEN])
{
size_t i, j;
i = 1;// 初始化 i 为 1
next[1] = j = 0;// 初始化 next[1] 为 0
// 当 i 小于等于模式串 T 的长度时进行循环
while (i <= strlen(T))
{
if (j == 0 || T[i - 1] == T[j - 1])
{
// 如果 j 为 0 或者当前字符匹配成功i 和 j 都加 1
++i;
++j;
next[i] = j;// 更新 next 数组
} else
{
j = next[j];// 如果不匹配,j 回溯到 next[j] 的位置
}
}
// 输出 next 数组的值
for (j = 1; j <= strlen(T); j++)
{
printf("next[%d]=%-3d", j, next[j]);
}
printf("\n");
return 0;
}
// 在主串 S 中从 pos 位置开始查找模式串 T 的位置
int IndexKMP(char S[MAXSTRLEN], char T[MAXSTRLEN], size_t next[MAXSTRLEN], size_t pos)
{
size_t i, j;
i = pos;// 初始化 i 为 pos
j = 1;// 初始化 j 为 1
// 当 i 小于等于主串 S 的长度且 j 小于等于模式串 T 的长度时进行循环
while (i <= strlen(S) && j <= strlen(T))
{
if (j == 0 || S[i - 1] == T[j - 1])
{
// 如果 j 为 0 或者当前字符匹配成功,i 和 j 都加 1
++i;
++j;
}
else
j = next[j];// 如果不匹配,j 回溯到 next[j] 的位置
}
if (j > strlen(T))
{
// 如果 j 大于模式串 T 的长度,说明找到了模式串,返回模式串在主串中的起始位置
return (i - strlen(T));
}
else
return 0;
}
运行结果: