小伙伴们好久不见,今天将开设“数据结构与算法”专栏,一起梳理一遍硬核课程的重要知识点,那我们开始吧

正文

「字符串匹配」是计算机的基本任务之一,举个栗子,有一个字符串“「aaaaaaca」",我想知道里面是否包含另一个字符串“「aaaac」”,该怎么办?

这里就会使用到「串的模式匹配算法」,最常见的分别是传统的「Brute-Force(暴力)算法」和「KMP算法」。

BF算法设计思想

1、主串和模式串逐个字符进行比较

2、当出现「字符串不相同」时,也就是「失配」时,主串的比较位置重置为起始位置的下一个字符位置,模式串的比较位置重置为起始位置

3、匹配成功后返回主串中匹配串的起始位置,否则就返回错误代码

BF算法的设计缺陷及解决方案

在BF算法中,每次失配都需要回溯指向上次比较起始字符的下一个字符。通过观察发现:在回溯的时候,已匹配似乎「有一部分」没必要继续比较了,这样可以降低算法的「时间复杂度」

「KMP」算法的出现有效地解决了BF算法的缺陷。KMP 算法是 D.E.Knuth、J,H,Morris 和 V.R.Pratt 三位神人共同提出的。

但是这种算法相对于BF算法不太容易理解,网上也有很多解释,但配图有点少,总感觉差点意思,下面我通过画图的方式详细介绍KMP算法的设计思想和工作原理

KMP算法设计思想

在匹配过程中出现字符比较不相等时,「主串 S」已比较的位置不回溯,「模式串 T」比较的位置进行移动

在匹配过程中有一个难题需要解决:如何计算「模式串 T」失配时的移动位数?经过三位牛人的研究,设计出了「部分匹配函数」

部分匹配函数

部分匹配函数是KMP算法中最难以理解的部分。首先需要理解「前缀」、「后缀」、「最大共有长度」的概念。

· 前缀:指除了最后一个字符以外,一个字符串的全部头部组合

· 后缀:指除了第一个字符以外,一个字符串的全部尾部组合

· 最大共有长度(部分匹配值):指前缀和后缀中的最大共有元素,没有则为0。例如“abab”的前缀为“a”、“ab”、“aba”,后缀为“b”、“ab”、“bab”,最大共有元素为“ab”,所以最大共有长度为 2

回顾一下KMP算法的匹配过程:

红线框出的部分恰好就是失配时已匹配部分,“aaaa” 的最大共有元素为 “aaa”,这一部分字符就是不需要再重复进行比较直接跳过的字符

在代码实现过程中,j 移动后的位置 = 模式串 T 的起始位置下标 + 部分匹配值。通常起始下标为 0,因此 j 移动后位置 = 部分匹配值,即 j = next[j],next[j] 就是「部分匹配函数」,j 为失配时的位置

因此接下来就成了对部分匹配函数的是实现。将 “aaaac” 以首字符起始的所有子串的最大共有长度枚举出来,构成「部分匹配表」,它描述了失配时的下标 j 与部分匹配值的关系

部分匹配表则是通过模式串 T 的自匹配实现:

示例代码(C语言哦):

/*KMP匹配算法*/

int KMPCompare(HString parent, HString child, intpos) {

int next[255];

Get_Next(child, next);

int i = pos - 1;

int j = 0;     //j用于子串child中的起始位置

while (i

if (j == 0 || parent.ch[i] == child.ch[j]) {

++i;

++j;

}

else {

j = next[j];    //i不变,j后退

}

}

if (j == child.length) {

return (i + 1) - j;

}

return 0;

}

/*部分匹配函数的实现*/

void Get_Next(HString child, int * next) {

int i = 0;

int j = -1;

next[0] = -1;   //不会用到

while (i

if (j == -1 || child.ch[i] == child.ch[j]) {

++i;

++j;

next[i] = j;

}

else {

j = next[j];

}

}

}

void main() {

/*使用KMP算法匹配串*/

HString parent, child;

StrAssign_HeapString(&parent, "BBC ABCDAB ABCDABCDABDE");

StrAssign_HeapString(&child, "ABCDABD");

printf("Index = %d\n", KMPCompare(parent, child, 1));

}

复制代码

关注即可提高学习效率!我是Aime菌,下期再见!Peace~

每天进步一点点,慢一点才能走得更快

c语言主范式与编码,超详细!终于搞明白KMP算法相关推荐

  1. c语言有关字符的操作,C语言字符操作总结大全(超详细).doc

    C语言字符串操作总结大全(超详细) 作者: 本篇文章是对C语言字符串操作进行了详细的总结分析,需要的朋友参考下 1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n ...

  2. 一年半´力扣´练习生超详细总结(附数据结构+算法)

    一年半´力扣´练习生超详细总结(附数据结构+算法) 文章目录 一年半´力扣´练习生超详细总结(附数据结构+算法) 我与力扣 数据结构 算法 未来计划 其他专栏推荐 我与力扣 专栏导航:LeetCode ...

  3. C语言基础入门笔记(超详细笔记,多出进行更新,将近九千字)

    下载VS2013,我们一起学习. #include 包含一个叫stdio.h的文件,文件包含令,预处理指令. stdio.h C语言的标准I/O库,用于读取和写入文件,也用于控制台的输入和输出. ma ...

  4. c++ 字符串连接_C语言字符串操作总结大全(超详细)

    本篇文章是对C语言字符串操作进行了详细的总结分析,需要的朋友参考下 1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strcat(p, ...

  5. C语言文件操作函数总结——超详细

    版权声明 本文原创作者:谷哥的小弟 作者博客地址:http://blog.csdn.net/lfdfhl 文件与流 在C语言中有三种标准流: stdin(standard input stream)标 ...

  6. Mac上安装R语言运行环境及RStudio [超详细!~]

    前言 我们需要安装:1)R语言环境,2)Rstudio软件(R语言开发工具). 我的安装方法参考了博文mac上安装R和RStudio,感谢作者. 接下来分步骤展示详细方法,并给出一个运行示例~ Ste ...

  7. 【C语言初级阶段学习1】使用vscode运行C语言,vscode配置环境超详细过程(包括安装vscode和MinGW-W64安装及后续配置使用的详细过程,vscode用户代码片段的使用)[考研专用]

    vscode配置c语言环境 前言 一.下载vscode和MinGW-W64和安装过程 1. vscode部分 1.1 vscode下载安装过程 1.2 vscode下载插件 2. MinGW-W64部 ...

  8. c语言1066字符分类统计,C语言字符串操作总结大全(超详细)

    1)字符串操作strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strcat(p, p1) 附加字符串 strncat(p, p1, n) 附加指定长度字 ...

  9. C语言字符串操作总结大全(超详细)

    1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strcat(p, p1) 附加字符串 strncat(p, p1, n) 附加指定长度 ...

最新文章

  1. 换掉VMware?轻量级虚拟机,横空出世!
  2. 比特币要升级成为“比特币现金”
  3. 重构第15天 移除重复的代码(Remove Duplication)
  4. 【转】grep搜索子目录中包含某字符串的特定文件
  5. 关于fflush、缓冲区、scanf、EOF等问题真麻烦
  6. Apache Kafka-通过concurrency实现并发消费
  7. Ubuntu环境使用conda安装轻量级中文ocr开源项目chineseocr_lite,最简单的方式
  8. Windows系统进程介绍
  9. JavaScript反向shell
  10. hdu2844 amp; poj1742 Coin ---多重背包--两种方法
  11. 成都东软学院大学生计算机基础excel作业,成都东软学院
  12. Matlab R2016a安装教程
  13. WPF介绍和一些基础操作
  14. cc2500的register操作
  15. BT5 U盘制作方法
  16. DTMF信号检测分析(Matlab)
  17. 关于一台电脑安装多个jdk后使用时如何切换
  18. 个人技术博客的选择:CSDN、博客园、简书、知乎专栏、Github、新浪、个人建站等?
  19. cesium城市建筑颜色渲染以及泛光渐变效果
  20. bzoj3926 诸神眷顾的幻想乡 后缀自动机

热门文章

  1. VTK修炼之道74:交互部件_Widget的创建
  2. 从用户接触到完成需求说明书
  3. linux-IO之copy的实现
  4. android.content.Context.getResources()‘ on a null object reference
  5. 如何用Linux写c程序并编译运行
  6. sort函数——利用函数实现快速排序c++
  7. 程序员面试系列——插入排序
  8. 8086处理器的无条件转移指令——《x86汇编语言:从实模式到保护模式》读书笔记13
  9. Object的finalize方法
  10. 汽车车牌识别系统(六)-- 项目中的各个文件解析