热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C语言中KMP字符串匹配算法详解及实现

KMP算法是一种高效的字符串模式匹配算法,能够在不进行回溯的情况下完成匹配,其时间复杂度为O(m+n),其中m和n分别为文本串和模式串的长度。本文将详细介绍KMP算法的工作原理,并提供C语言实现。

KMP算法是一种高效的字符串模式匹配算法,它通过预处理模式串来避免不必要的回溯,从而提高匹配效率。该算法的时间复杂度为O(m+n),其中m为文本串的长度,n为模式串的长度。

算法的核心在于构建一个next数组,该数组记录了模式串中每个位置的最大相同前后缀长度。具体来说,对于模式串P = “p0p1p2...pn”,如果已知p0 = pk, p1 = pk+1, ..., pi = pk+i,则当pk+i+1匹配失败时,可以直接将模式串向右移动,使pi对齐pk+i的位置,而无需重新检查pi及其之前的字符,因为它们已经匹配成功。同时,为了确保不遗漏任何可能的匹配,需要保证对于“p0...pk+i”不存在更大的i和更小的k使得上述条件成立,否则可能会错误地将模式串右移过长的距离。

对于模式串P的任意字符Pr,存在一个特定的下标k(r),使得从p0到pk(r)-1与从pr-k(r)到pr-1是Pr之前部分字符串的最长相同前后缀。在匹配过程中,如果Pr和文本串中的某个字符匹配失败,可以直接使用pk(r)与之比较。

下面是KMP算法的C语言实现:

#include 
#include

#define SRC_LEN 100
#define MDL_LEN 20

// 构建next数组
void makeNext(const char *model, int *next, int len) {
int index = 0, k = -1;
next[0] = -1;
while (index while (k >= 0 && model[index] != model[k])
k = next[k];
index++, k++;
if (model[index] == model[k])
next[index] = next[k];
else
next[index] = k;
}
}

// 匹配函数
void match(const char *source, const char *model, int *index) {
int srcIndex = 0, mdlIndex = 0;
int srcLen = strlen(source), mdlLen = strlen(model);
int *next = (int *)malloc(mdlLen * sizeof(int));
makeNext(model, next, mdlLen);
while (mdlIndex if (mdlIndex == -1 || source[srcIndex] == model[mdlIndex]) {
mdlIndex++, srcIndex++;
} else {
mdlIndex = next[mdlIndex];
}
}
if (mdlIndex >= mdlLen)
*index = srcIndex - mdlLen;
else
*index = -1;
}

int main() {
char source[SRC_LEN], model[MDL_LEN];
int index;
printf("请输入源字符串: ");
fgets(source, SRC_LEN, stdin);
printf("请输入模式字符串: ");
fgets(model, MDL_LEN, stdin);
model[strcspn(model, "\n")] = 0; // 去除输入末尾的换行符
source[strcspn(source, "\n")] = 0; // 去除输入末尾的换行符
match(source, model, &index);
printf("匹配位置: %d\n", index);
return 0;
}

以上代码实现了KMP算法的基本功能,包括构建next数组和执行匹配过程。用户可以通过输入源字符串和模式字符串来测试算法的正确性和效率。


推荐阅读
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • MySQL索引详解与优化
    本文深入探讨了MySQL中的索引机制,包括索引的基本概念、优势与劣势、分类及其实现原理,并详细介绍了索引的使用场景和优化技巧。通过具体示例,帮助读者更好地理解和应用索引以提升数据库性能。 ... [详细]
  • Codeforces Round #566 (Div. 2) A~F个人题解
    Dashboard-CodeforcesRound#566(Div.2)-CodeforcesA.FillingShapes题意:给你一个的表格,你 ... [详细]
  • 毕业设计:基于机器学习与深度学习的垃圾邮件(短信)分类算法实现
    本文详细介绍了如何使用机器学习和深度学习技术对垃圾邮件和短信进行分类。内容涵盖从数据集介绍、预处理、特征提取到模型训练与评估的完整流程,并提供了具体的代码示例和实验结果。 ... [详细]
  • 在多线程编程环境中,线程之间共享全局变量可能导致数据竞争和不一致性。为了解决这一问题,Linux提供了线程局部存储(TLS),使每个线程可以拥有独立的变量副本,确保线程间的数据隔离与安全。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • 本文详细介绍了如何构建一个高效的UI管理系统,集中处理UI页面的打开、关闭、层级管理和页面跳转等问题。通过UIManager统一管理外部切换逻辑,实现功能逻辑分散化和代码复用,支持多人协作开发。 ... [详细]
  • 本文详细介绍了C语言中链表的两种动态创建方法——头插法和尾插法,包括具体的实现代码和运行示例。通过这些内容,读者可以更好地理解和掌握链表的基本操作。 ... [详细]
  • 本文详细探讨了VxWorks操作系统中双向链表和环形缓冲区的实现原理及使用方法,通过具体示例代码加深理解。 ... [详细]
  • 本教程涵盖OpenGL基础操作及直线光栅化技术,包括点的绘制、简单图形绘制、直线绘制以及DDA和中点画线算法。通过逐步实践,帮助读者掌握OpenGL的基本使用方法。 ... [详细]
author-avatar
变更后2010
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有