[c语言日寄]字符串进阶:KMP算法

在这里插入图片描述

【作者主页】siy2333
【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是进阶开发者,这里都能满足你的需求!
【食用方法】1.根据题目自行尝试 2.查看基础思路完善题解 3.学习拓展算法
【Gitee链接】资源保存在我的Gitee仓库:https://gitee.com/siy2333/study


文章目录

  • 1. 前言:为什么需要KMP算法?
  • 2. 知识点分析:KMP 的核心思想与实现
    • 2.1 部分匹配表(Next 数组)
    • 2.2 Next 数组的构建逻辑
    • 2.3 匹配过程的优化
  • 3. 注意事项
    • 3.1 数组越界问题
    • 3.2 特殊长度的处理
    • 3.3 指针有效性检查
    • 3.4 内存管理
  • 4. 拓展应用
    • 4.1 多模式匹配
    • 4.2 循环子串检测
  • 总结


1. 前言:为什么需要KMP算法?

在字符串匹配领域,暴力匹配算法(Brute-Force)是最直观的解决方案:遍历主串的每个字符作为起点,依次与模式串的字符匹配,若发现不匹配则回退主串指针并重新尝试。这种算法的时间复杂度为 O(m×n)(m 和 n 分别是主串和模式串的长度),在面对长文本或高频次匹配时效率极低。

例如,当主串为 "AAAAA...AAAAA"(含 1000 个 A),模式串为 "AAAAB" 时,暴力算法需要回退主串指针近千次,而 KMP 算法(Knuth-Morris-Pratt)通过避免无意义的回退,将时间复杂度优化为 O(m+n),成为解决字符串匹配问题的经典方案。

然而,KMP 的实现细节复杂,尤其是 Next 数组的构建指针回退逻辑,稍有不慎就会导致数组越界或逻辑错误。本文将结合代码案例,深入分析 KMP 的实现要点与常见陷阱。


2. 知识点分析:KMP 的核心思想与实现

2.1 部分匹配表(Next 数组)

KMP 的核心在于预处理模式串生成 Next 数组,它记录了模式串每个位置的最长公共前后缀长度。例如,模式串 "ABABCABAB" 的 Next 数组如下:

| 索引 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|------|—|—|—|—|—|—|—|—|—|—|
| 字符 | A | B | A | B | C | A | B | A | B |
| Next | -1| 0 | 0 | 1 | 2 | 0 | 1 | 2 | 3 |

Next 数组的作用:当字符匹配失败时,根据 Next 值决定模式串指针回退的位置,避免主串指针回溯。

2.2 Next 数组的构建逻辑

Next 数组的构建是一个动态规划过程,核心代码如下(修正后):

void kmp_GetNextArr(char* sub, int* next, int len_sub) {assert(sub && next);if (len_sub == 0) return;next[0] = -1;if (len_sub == 1) return; // 处理长度为1的情况next[1] = 0;int i = 1;int k = next[i]; // k=0while (i < len_sub - 1) { // 避免越界if (k == -1 || sub[i] == sub[k]) {next[i + 1] = k + 1;i++;k++;} else {k = next[k];}}
}

关键点

  • 初始条件next[0] = -1 表示无前缀可匹配,next[1] = 0 因为单个字符无公共前后缀。
  • 递推逻辑:若 sub[i] == sub[k],则 next[i+1] = k+1;否则,递归回退 k = next[k]
  • 越界修复:循环条件改为 i < len_sub - 1,避免访问 next[len_sub]

2.3 匹配过程的优化

匹配时主串指针永不回退,模式串指针根据 Next 数组回退:

int my_kmp(char* str, char* sub) {// ... 初始化与Next数组构建int i = 0, j = 0;while (i < len_str && j < len_sub) {if (j == -1 || str[i] == sub[j]) {i++;j++;} else {j = next[j]; // 关键回退逻辑}}return (j == len_sub) ? (i - j) : -1;
}

3. 注意事项

3.1 数组越界问题

  • 问题场景:构建 Next 数组时,若循环条件为 i < len_sub,当 i = len_sub-1 时会计算 next[len_sub],导致越界。
  • 修复方法:限制循环条件为 i < len_sub - 1

3.2 特殊长度的处理

  • 长度为1的模式串:若模式串长度为1,代码中不应设置 next[1](因为 next 数组仅有一个元素)。
  • 修复方法:增加长度检查 if (len_sub == 1) return;

3.3 指针有效性检查

  • 断言保护:在函数入口使用 assert 检查指针非空,避免空指针解引用。

3.4 内存管理

  • 动态分配:Next 数组需使用 malloc 申请内存,并在使用后及时释放(用户代码中未释放,实际需补充 free(next))。

4. 拓展应用

4.1 多模式匹配

KMP 可扩展为 AC 自动机(Aho-Corasick Algorithm),用于同时匹配多个模式串。例如,在敏感词过滤系统中,通过构建 Trie 树和失败指针(类似 Next 数组),实现高效的多模式匹配。

4.2 循环子串检测

利用 Next 数组的特性,可以判断字符串是否由某个子串重复构成。例如,字符串 "ABABAB" 的 Next 数组为 [-1, 0, 0, 1, 2, 3],若 len % (len - next[len]) == 0,则说明存在循环节。


总结

KMP 算法通过预处理模式串生成 Next 数组,避免了主串指针的回退,显著提升了匹配效率。然而,其实现细节需严格处理边界条件(如数组越界、特殊长度),否则易引发运行时错误。理解 Next 数组的动态规划构建逻辑,是掌握 KMP 算法的关键。此外,KMP 的思想还可扩展到更复杂的场景(如多模式匹配),成为解决字符串处理问题的基石。

关注窝,每三天至少更新一篇优质c语言题目详解~

[专栏链接QwQ] :⌈c语言日寄⌋CSDN
[关注博主ava]:siy2333
感谢观看~ 我们下次再见!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/33676.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android源码学习之Overlay

在 Android Framework 开发中&#xff0c;Overlay 主要用于修改和替换系统或应用的资源&#xff0c;而无需直接修改源码&#xff0c;与源码解耦。Overlay 机制可以分为 两种类型&#xff1a; 静态 Overlay&#xff08;Static Resource Overlay, SRO&#xff09; 在 编译时 覆…

【MySQL】基本操作 —— DDL

目录 DDLDDL 常用操作对数据库的常用操作查看所有数据库创建数据库切换、显示当前数据库删除数据库修改数据库编码 对表的常用操作创建表数据类型数值类型日期和时间类型字符串类型 查看当前数据库所有表查看指定表的创建语句查看指定表结构删除表 对表结构的常用操作给表添加字…

网络安全需要学多久才能入门?

网络安全是一个复杂且不断发展的领域&#xff0c;想要入行该领域&#xff0c;我们需要付出足够多的时间和精力好好学习相关知识&#xff0c;才可以获得一份不错的工作&#xff0c;那么网络安全需要学多久才能入门?我们通过这篇文章来了解一下。 学习网络安全的入门时间因个人的…

【测试语言基础篇】Python基础之List列表

一、Python 列表(List) 序列是Python中最基本的数据结构。序列中的每个元素都分配一个数字 - 它的位置&#xff0c;或索引&#xff0c;第一个索引是0&#xff0c;第二个索引是1&#xff0c;依此类推。 Python有6个序列的内置类型&#xff0c;但最常见的是列表和元组。序列都可…

编译系统设计原理概述

目录 简介 词法分析 正则表达式 有穷状态自动机 从正则表达式到有穷自动机的转换 单词识别 简介 主要介绍编译系统设计过程中涉及的原理与技术&#xff0c;主要分为前端设计和后端设计两 个模块。前端部分包括词法分析器、语法分析器的构建和语义分析过程的设计…

ArcGIS Pro 车牌分区数据处理与地图制作全攻略

在大数据时代&#xff0c;地理信息系统&#xff08;GIS&#xff09;技术在各个领域都有着广泛的应用&#xff0c;而 ArcGIS Pro 作为一款功能强大的 GIS 软件&#xff0c;为数据处理和地图制作提供了丰富的工具和便捷的操作流程。 车牌数据作为一种重要的地理空间数据&#xf…

前端登录鉴权全解析:主流方案对比与实现指南

文章目录 一、常见登录鉴权方式概览1.1 主流方案对比1.2 技术特性对比 二、Session/Cookie方案2.1 实现原理2.2 代码实现2.3 优缺点分析 三、JWT方案3.1 实现原理3.2 代码实现3.3 优缺点分析 四、OAuth方案4.1 实现原理4.2 代码实现4.3 优缺点分析 五、SSO方案5.1 实现原理5.2 …

算法系列之回溯算法求解数独及所有可能解

有没有对数独感兴趣的朋友呢&#xff1f;数独作为一款经典的逻辑游戏&#xff0c;其目标是在一个9x9的方格中填入数字1至9&#xff0c;确保每一行、每一列以及每一个3x3的子网格中都包含这些数字且不重复。尽管数独的规则看似简单&#xff0c;但编写一个能够自动求解数独的程序…

华为hcia——Datacom实验指南——TCP传输原理和数据段格式

什么是TCP TCP是一种可靠的端到端的传输层协议&#xff0c;仅应用于单波通信。 采用TCP协议作为传输方式的应用层服务&#xff0c;再进行数据传输前&#xff0c;都需要进行TCP协议的创建。 TCP报文的格式 sequence number&#xff08;序列号&#xff09; 占4个字节&#x…

Vlog 片头制作

打开剪映&#xff0c;新建草稿&#xff0c;导入黑色背景。 拉长时间轴&#xff0c;背景时常调整为4.2秒。 添加文本&#xff0c;输入 5 个“|”&#xff0c;每个中间 2 个空格&#xff0c;如下| | | | |&#xff0c;然后手动放大文本&#xff0c;让中间显示出四个间隔。 继续添…

【Nacos】服务发布之优雅预热上线方案

目录 一、背景二、注册时机2.1、注册机制2.2、分析源码找到注册时机 三、注册前心跳健康检测3.1、方案实施3.2、源码分析3.3、优化代码 四、流量权重配置五、总结5.1、整体完整流程&#xff1a;5.2、流程图&#xff1a;5.1、优化方案完整代码&#xff1a; 一、背景 有些面向广…

VXLAN 组播 RP

一、Anycast RP 在每个 VTEP 上&#xff0c;每个多播组都会建立一个源树 (S,G)&#xff0c;并且在双活 Leaf 设备上到 RP 地址是 ECMP 路径。 在 PIM ASM 模式下&#xff0c;(S,G) 组在 VTEP 端创建。由于每个 VTEP 都能够为特定的多播组发送和接收多播流量&#xff0c;因此每…

【第七节】windows sdk编程:Windows 中的对话框

目录 引言 一、对话框简介 1.1 对话框的创建 1.2 基本函数 1.3 模态对话框与非模态对话框 1.4 对话框与窗口的区别 二、模态对话框编程方法 2.1 模态对话框编程 2.2 消息框 三、非模态对话框编程方法 四、综合代码案例 引言 在Windows应用程序开发中&#xff0c;对话…

安装并配置终端字体

1. 简介 在使用 Oh My Zsh Powerlevel10k 时&#xff0c;正确的字体配置至关重要。Powerlevel10k 依赖 Nerd Fonts 扩展字体&#xff0c;以正确显示 Git 状态、分支、时间、图标等信息。 如果没有正确配置字体&#xff0c;你可能会看到 乱码、问号&#xff08;?&#xff09…

LeetCode - #227 基于 Swift 实现基本计算器

摘要 在这篇文章中&#xff0c;我们将实现一个基于 Swift 语言的基本计算器。该计算器能够解析和计算包含 、-、* 和 / 的数学表达式&#xff0c;并且遵循运算符的优先级规则。整数除法仅保留整数部分&#xff0c;不能使用 eval() 这样的内置解析方法。 描述 给你一个字符串表…

智慧应急消防解决方案(35页PPT)(文末有下载方式)

详细资料请看本解读文章的最后内容。在当今社会&#xff0c;消防安全至关重要&#xff0c;关乎人民生命财产安全和社会稳定。随着科技的飞速发展&#xff0c;智慧应急消防解决方案应运而生&#xff0c;为消防工作带来了新的变革和机遇。接下来&#xff0c;让我们深入探讨这份智…

网络安全反渗透 网络安全攻防渗透

网络渗透防范主要从两个方面来进行防范&#xff0c;一方面是从思想意识上进行防范&#xff0c;另一方面就是从技术方面来进行防范。 1.从思想意识上防范渗透 网络攻击与网络安全防御是正反两个方面&#xff0c;纵观容易出现网络安全事故或者事件的公司和个人&#xff0c;在这些…

2025-03-15 学习记录--C/C++-PTA 练习3-4 统计字符

合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、题目描述 ⭐️ 练习3-4 统计字符 本题要求编写程序&#xff0c;输入10个字符&#xff0c;统计其中英文字母、空格或回车、…

11a-PPDU

## 前导码和信令 OFDM 物理层&#xff08;PHY&#xff09;的 PPDU&#xff08;物理层协议数据单元&#xff09;格式包含以下实体信息&#xff1a; - **PPDU 组成**&#xff1a;由 OFDM PHY preamble&#xff08;前导码&#xff0c;12 个符号&#xff09;、PHY header&#xff…

TF-IDF:文本挖掘中的关键词提取利器

引言 在自然语言处理&#xff08;NLP&#xff09;和文本挖掘中&#xff0c;TF-IDF是一种常用的技术&#xff0c;用于评估一个词在文档中的重要性。它不仅在信息检索领域广泛应用&#xff0c;还在文本分类、关键词提取等任务中发挥着重要作用。本文将详细介绍TF-IDF的原理…