【数据结构】数组和字符串(十五):字符串匹配2:KMP算法(Knuth-Morris-Pratt)

文章目录

  • 4.3 字符串
    • 4.3.1 字符串的定义与存储
    • 4.3.2 字符串的基本操作
    • 4.3.3 模式匹配算法
      • 0. 朴素模式匹配算法
      • 1. ADL语言
      • 2. KMP算法分析
      • 3. 手动求失败函数
        • 定义
        • 例1
        • 例2
        • 例3
      • 4. 自动求失败函数(C语言)
      • 5. KMP算法(C语言)
      • 6. 失败函数答案
        • 例2
        • 例3

4.3 字符串

  字符串(String)是由零个或多个字符(char)顺序排列组成的有限序列,简称为串。例如 “good morning”就是由12个字符构成的一个字符串。一般把字符串记作:

S = ′ ′ a 0 a 1 … a n − 1 ′ ′ S=''a_{0} a_{1}…a_{n-1}'' S=′′a0a1an1′′

  其中S是串名,引号中的字符序列是串值。字符个数是串的长度,长度为0的串被称为空串,因为它不包含任何字符。需要注意的是,空格字符(" ")并不是空串,因为它包含一个字符——空格。
  若把某个串称为主串,则主串中任意个连续的字符组成的子序列被称为子串。子串在主串中第一次出现时,其首字符在主串中的序号被称为该子串在主串中的位置。
  关于字符串的基础知识亦可参考前文:
【重拾C语言】六、批量数据组织(三)数组初值;字符串、字符数组、字符串数组;类型定义 typedef
【重拾C语言】七、指针(三)指针与字符串(字符串与字符串数组;指针与字符串的遍历、拷贝、比较;反转字符串

4.3.1 字符串的定义与存储

  字符串在许多非数值计算问题中扮演着重要的角色,并在模式匹配、程序编译和数据处理等领域得到广泛应用。在高级程序设计语言中,字符串通常被定义为以特殊字符’\0’(称为空字符或字符串结束符)结尾的字符序列。这个约定使得在处理字符串时可以方便地确定字符串的结束位置。关于字符串的存储方式,主要有两种常见的方式:

  • 顺序存储:字符串的字符按照顺序依次存储在连续的内存空间中。这种方式使得字符串的访问和操作效率较高,可以通过索引直接访问任意位置的字符。在顺序存储方式中,字符串的长度可以通过计算字符个数或者遇到’\0’结束符来确定。

  • 链式存储:字符串的字符通过链表的方式进行存储。每个节点包含一个字符和指向下一个节点的指针。链式存储方式可以动态地分配内存,适用于长度可变的字符串。但是相比于顺序存储,链式存储方式需要更多的内存空间,并且访问字符需要遍历链表。

  选择何种存储方式取决于具体的应用场景和需求。顺序存储适合于需要频繁访问和操作字符串的情况,而链式存储适合于长度可变的字符串或者对内存空间要求较高的情况。具体C语言实现可参照前文:
  【数据结构】数组和字符串(十一):字符串的定义与存储(顺序存储、链式存储及其C语言实现)

4.3.2 字符串的基本操作

顺序存储:【数据结构】数组和字符串(十二):顺序存储字符串的基本操作(串长统计、查找、复制、插入、删除、串拼接)
链式存储:【数据结构】数组和字符串(十三):链式字符串的基本操作(串长统计、查找、复制、插入、删除、串拼接)

4.3.3 模式匹配算法

  文本编辑器中常用的“查找”、“替换”和“全部替换”等基本的编辑操作就是最普通的模式匹配问题,即:在文本文件中查找串。它的查找过程可简单描述如下:给定两个字符串变量 S 和 P,其中目标串 S 有n个字符,模式串P有m个字符,m≤n . 从S的给定位置(通常为S的第一个字符)开始,搜索模式串P,如果找到,返回模式串P在S中匹配成功的起始位置;如果没找到(即S中没有P),则返回–1 .
  字符串匹配可以采用多种算法,包括朴素模式匹配算法、KMP(Knuth-Morris-Pratt)算法、Boyer-Moore算法等。这些算法的性能和效率各不相同,具体选择取决于应用的需求和文本数据的规模。

0. 朴素模式匹配算法

  • 朴素模式匹配算法:【数据结构】数组和字符串(十四):字符串匹配1:朴素的模式匹配算法(StringMatching)
      朴素模式匹配算法的优点是过程简单,缺点是效率低。在最坏情况下,该算法要匹配n-m+1次,每次匹配要做m次比较。本文将介绍更高效的模式匹配算法——KMP算法

1. ADL语言

在这里插入图片描述

2. KMP算法分析

待完善

3. 手动求失败函数

定义

在这里插入图片描述

例1

在这里插入图片描述

例2

在这里插入图片描述

例3

在这里插入图片描述
答案见文末

4. 自动求失败函数(C语言)

在这里插入图片描述

#include <stdio.h>
#include <string.h>void buildFailureFunction(const char* P, int m, int* F) {int i = 1, j = 0;F[0] = -1;while (i < m) {if (P[i] == P[j]) {j++;F[i] = j - 1;i++;} else {if (j != 0) {j = F[j - 1];} else {F[i] = -1;i++;}}}
}int main() {
//    const char* P = "abcdabc";
//    const char* P = "aaaabbaabb";const char* P = "abcabcabcabcabcabc";int m = strlen(P);int F[m];buildFailureFunction(P, m, F);printf("模式串P: %s\n", P);printf("失败函数F(P): ");for (int i = 0; i < m; i++) {printf("%d ", F[i]);}printf("\n");return 0;
}

5. KMP算法(C语言)

#include <stdio.h>
#include <string.h>void buildFailureFunction(const char* P, int m, int* F) {int i = 1, j = 0;F[0] = 0;while (i < m) {if (P[i] == P[j]) {j++;F[i] = j;i++;} else {if (j != 0) {j = F[j - 1];} else {F[i] = 0;i++;}}}
}int kmpPatternMatching(const char* S, const char* P, int* comparisons) {int n = strlen(S);  // 目标串的长度int m = strlen(P);  // 模式串的长度int position = -1;  // 初始化位置为-1int F[m];  // 失败函数表buildFailureFunction(P, m, F);int i = 0, j = 0;while (i < n) {(*comparisons)++;  // 比较次数加1if (S[i] == P[j]) {i++;j++;if (j == m) {  // 如果模式串完全匹配position = i - m;break;}} else {if (j != 0) {j = F[j - 1];} else {i++;}}}return position;
}int naivePatternMatching(const char* S, const char* P, int* comparisons) {int n = strlen(S);  // 目标串的长度int m = strlen(P);  // 模式串的长度int position = -1;  // 初始化位置为-1for (int i = 0; i <= n - m; i++) {int j = 0;while (j < m && S[i + j] == P[j]) {(*comparisons)++;  // 比较次数加1j++;}if (j == m) {  // 如果模式串完全匹配position = i;  // 设置匹配位置break;}}return position;
}int main() {const char* S = "abcabcabcabcabcabd";const char* P = "abcabd";int comparisons = 0;  // 比较次数初始化为0int result1 = naivePatternMatching(S, P, &comparisons);if (result1 != -1) {printf("朴素模式匹配算法:模式串在目标串中的位置: %d\n", result1);} else {printf("未找到匹配\n");}printf("朴素模式匹配算法:比较次数: %d\n", comparisons);comparisons = 0;  // 比较次数初始化为0int result2 = kmpPatternMatching(S, P, &comparisons);if (result2 != -1) {printf("KMP算法:模式串在目标串中的位置: %d\n", result2);} else {printf("未找到匹配\n");}printf("KMP算法:比较次数: %d\n", comparisons);return 0;
}

在这里插入图片描述

6. 失败函数答案

例2

在这里插入图片描述
在这里插入图片描述

例3

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

STM32F103C8T6第二天:按键点灯轮询法和中断法、RCC、电动车报警器(振动传感器、继电器、喇叭、433M无线接收发射模块)

1. 点亮LED灯详解&#xff08;307.11&#xff09; 标号一样的导线在物理上是连接在一起的。 将 PB8 或 PB9 拉低&#xff0c;就可以实现将对应的 LED 灯点亮。常用的GPIO HAL库函数&#xff1a; void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);//I/…

产品经理入门学习(二):产品经理问题思考维度

参考引用 黑马-产品经理入门基础课程 1. 抓住核心用户 1.1 为什么要抓住核心用户 什么是用户&#xff1f; 所有和产品有关系的群体就是用户&#xff0c;他们是一群既有共性&#xff0c;又有差异的群体组合 做产品为什么要了解用户&#xff1f; 了解用户的付费点、更好的优化产…

【软考中级】软件设计师-下午题

下午题 试题一 黑洞&#xff1a;加工有输入无输出 白洞(奇迹)&#xff1a;加工有输出无输入 灰洞&#xff1a;数据流输入的加工不足以产生输出 结构化语言&#xff1a; IF *** THEN ELSE IF *** THEN ******* END IF END IF 数据流的父子图平衡&#xff0c;如果父子图平衡就不…

【CIO人物展】黄淮学院副CIO周鹏:构建数智化平台赋能学校高质量发展

周鹏 本文由黄淮学院副CIO周鹏投递并参与《2023中国数智化转型升级优秀CIO》榜单/奖项评选。丨推荐企业—锐捷网络 大数据产业创新服务媒体 ——聚焦数据 改变商业 黄淮学院是2004年经教育部批准成立的一所省属全日制普通本科高校。学校位于素有“豫州之腹地、天下之最中”之美…

地理信息系统原理-空间数据结构(7)

​四叉树编码 1.四叉树编码定义 四叉树数据结构是一种对栅格数据的压缩编码方法&#xff0c;其基本思想是将一幅栅格数据层或图像等分为四部分&#xff0c;逐块检查其格网属性值&#xff08;或灰度&#xff09;&#xff1b;如果某个子区的所有格网值都具有相同的值&#xff0…

Linux----------------Shell重定向输入输出

&#xff08;一&#xff09; 标准输入 以键盘读取用户输入的数据&#xff0c;然后再把数据拿到 Shel程序中使用。 标准输出 Shell 程序产生的数据&#xff0c;这些数据一般都是呈现到显示器上供用户浏览查看 输入输出重定向 输入方向就是数据从哪里流向程序。数据默认从键…

【使用Python编写游戏辅助工具】第五篇:打造交互式游戏工具界面:PySide6/PyQT高效构建GUI工具

前言 这里是【使用Python编写游戏辅助工具】的第五篇&#xff1a;打造交互式游戏工具界面&#xff1a;PySide6/PyQT高效构建GUI工具。本文主要介绍使用PySide6来实现构建GUI工具。 在前面&#xff0c;我们实现了两个实用的游戏辅助功能&#xff1a; 由键盘监听事件触发的鼠标连…

IntelliJ IDEA 2023 最新版如何试用?IntelliJ IDEA 2023最新版试用方法及验证ja-netfilter配置成功提示

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

[极客大挑战 2019]Http 1

题目环境&#xff1a; 看起来挺花里胡哨的 F12查看源代码寻找隐藏文件 这是啥子呀&#xff0c;果然防不胜防 点击隐藏文件Secret.php 它不是来自这个地址的请求 报头&#xff1a;https://Sycsecret.buuoj.cn 需要抓包&#xff0c;在抓包前了解部分数据包参数 GET:到 Host:来自 …

ElementUI 自定义 Tree 树形控件背景

在 template 中 <div class"container"><el-tree :data"treeList" :props"defaultProps" accordion node-click"handleNodeClick" /> </div> 在 script 中 treeList: [{ id: "-1", label: "区域选…

由于flutter_app依赖于flutter_swiper>=0.0.2,不支持零安全,版本解决失败。

参考 dart3.0使用flutter_swiper报错记录 flutter_swiper package - All Versions从官网的信息可以看到 Dart3版本不兼容 最小兼容的Dart SDK版本需要2.0 Flutter SDK 版本列表Flutter SDK 版本列表 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 说明&#xff1a;因…

算法:Java构建二叉树并递归实现二叉树的前序、中序、后序遍历

先自定义一下二叉树的类&#xff1a; // Definition for a binary tree node. public class TreeNode {int val;TreeNode left;TreeNode right;TreeNode() {}TreeNode(int val) { this.val val; }TreeNode(int val, TreeNode left, TreeNode right) {this.val val;this.left…

对Java的多线程的理解

说说对Java线程的理解 下面是AI的回答 Java线程就是Java程序里面可以同时运行多个任务。Java提供了几种创建和管理线程的方式&#xff0c;其中一种是继承Thread类&#xff0c;另一种是实现Runnable接口或Callable接口。jdk5提供了线程池&#xff0c;可以更方便地创建、启动和终…

理解springboot那些过滤器与调用链、包装或封装、设计模式相关等命名规范,就可以读懂80%的springboot源代码,和其他Java框架代码

紧接上面《 理解springboot那些注册与回调、监控与统计等命名规范,就可以读懂70%的springboot源代码》、《 理解springboot那些约定俗成的框架类名、全局context等命名规范,就可以读懂一半springboot的源代码》2篇文章,此片将汇总springboot那些过滤器与调用链、包装或封装…

【多线程】龟兔赛跑

package org.example;public class Race implements Runnable {//胜利者private static String winner;Overridepublic void run() {for(int i0;i<100;i){boolean flag gameOver(i);//如果flag>100,结束比赛if(flag){break;}System.out.println(Thread.currentThread().g…

Adobe After Effects 2024(Ae2024)在新版本中的升级有哪些?

After Effects 2024是Adobe公司推出的一款视频处理软件&#xff0c;它适用于从事设计和视频特技的机构&#xff0c;包括电视台、动画制作公司、个人后期制作工作室以及多媒体工作室。通过After Effects&#xff0c;用户可以高效且精确地创建无数种引人注目的动态图形和震撼人心…

DAY43 完全背包理论基础 + 518.零钱兑换II

完全背包 有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品都有无限个&#xff08;也就是可以放入背包多次&#xff09;&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 完全背包和01背包问题唯一不同…

[SSD综述1.7] SSD接口形态: SATA、M.2、U.2、PCIe、BGA

依公知及经验整理,原创保护,禁止转载。 专栏 《SSD入门到精通系列》 <<<< 返回总目录 <<<< 前言 犹记得当年Windows 7系统体验指数中,那5.9分磁盘分数,在其余四项的7.9分面前,似乎已经告诉我们机械硬盘注定被时代淘汰。势如破竹的SSD固态硬盘,彻…

ChatGPT 的 Text Completion

该章节我们来学习一下 “Text Completion” &#xff0c;也就是 “文本完成” 。“Text Completion” 并不是一种模型&#xff0c;而是指模型能够根据上下文自动完成缺失的文本部分&#xff0c;生成完整的文本。 ⭐ Text Completion 的介绍 Text Completion 也称为文本自动补全…

机器人连杆惯量参数辨识(估计)

杆的转动惯量的计算公式是Imr^2。在经典力学中&#xff0c;转动惯量&#xff08;又称质量惯性矩&#xff0c;简称惯矩&#xff09;通常以I 或J表示&#xff0c;SI 单位为 kgm。对于一个质点&#xff0c;I mr&#xff0c;其中 m 是其质量&#xff0c;r 是质点和转轴的垂直距离。…