热门标签 | 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数组和执行匹配过程。用户可以通过输入源字符串和模式字符串来测试算法的正确性和效率。


推荐阅读
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 毕业设计:基于机器学习与深度学习的垃圾邮件(短信)分类算法实现
    本文详细介绍了如何使用机器学习和深度学习技术对垃圾邮件和短信进行分类。内容涵盖从数据集介绍、预处理、特征提取到模型训练与评估的完整流程,并提供了具体的代码示例和实验结果。 ... [详细]
  • 在多线程编程环境中,线程之间共享全局变量可能导致数据竞争和不一致性。为了解决这一问题,Linux提供了线程局部存储(TLS),使每个线程可以拥有独立的变量副本,确保线程间的数据隔离与安全。 ... [详细]
  • 本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 本文探讨了如何在模运算下高效计算组合数C(n, m),并详细介绍了乘法逆元的应用。通过扩展欧几里得算法求解乘法逆元,从而实现除法取余的计算。 ... [详细]
  • 本文探讨了如何在给定整数N的情况下,找到两个不同的整数a和b,使得它们的和最大,并且满足特定的数学条件。 ... [详细]
  • 本文探讨了 C++ 中普通数组和标准库类型 vector 的初始化方法。普通数组具有固定长度,而 vector 是一种可扩展的容器,允许动态调整大小。文章详细介绍了不同初始化方式及其应用场景,并提供了代码示例以加深理解。 ... [详细]
  • 本文详细探讨了VxWorks操作系统中双向链表和环形缓冲区的实现原理及使用方法,通过具体示例代码加深理解。 ... [详细]
  • 本教程涵盖OpenGL基础操作及直线光栅化技术,包括点的绘制、简单图形绘制、直线绘制以及DDA和中点画线算法。通过逐步实践,帮助读者掌握OpenGL的基本使用方法。 ... [详细]
  • Codeforces Round #566 (Div. 2) A~F个人题解
    Dashboard-CodeforcesRound#566(Div.2)-CodeforcesA.FillingShapes题意:给你一个的表格,你 ... [详细]
  • 本文介绍如何使用Objective-C结合dispatch库进行并发编程,以提高素数计数任务的效率。通过对比纯C代码与引入并发机制后的代码,展示dispatch库的强大功能。 ... [详细]
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社区 版权所有