数据结构之串的模式匹配--KMP算法-利用next数组的代码实现

代码实现了 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;
}    

 运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值