朴素模式匹配算法和KMP匹配算法

一、朴素模式

假设我们要从主串S=”goodgoogle"中找到子串T=“google"的位置,步骤如下:

i表示主串的当前位置下标,j表示子串的当前位置下标,如上图在第一轮比较(i=1开始)中j=4和i=4的位置不匹配,接下来就要指针回退,从i=2开始比较,如下:

如此反复直到比较到 i =(主串长度-子串长度+1)的位置或者 j = 子串的长度 就退出比较循环,上面的主串和子串在比较到i=5的位置就完全匹配了。

#include <stdio.h>int Index(const char S[], const char T[], int pos){int i = pos; //主串当前下标int j = 1;  //子串当前下标//S[0]是主串的长度,T[0]是子串的长度while(i <= S[0] && j <= T[0]){//如果相等则继续向下比较if(S[i] == T[j]) {++i;++j;//如果不等则指针回退}else{i = i - j + 2; //主串回退j = 1;}}//j>T[0]则说明子串被完全匹配if( j > T[0]) return i - T[0];else return 0;
}int main(){char S[] = {10, 'g', 'o', 'o', 'd', 'g', 'o', 'o','g', 'l', 'e'};  char T[] = {6, 'g', 'o', 'o', 'g', 'l', 'e'};int i =  Index(S, T, 1);printf("%d\n", i);return 0;
}

分析一下这种匹配算法最好的情况时间复杂度是O(m),即主串的前m个字符刚好与子串相等,最坏的情况是每次最后一个字符不匹配,时间复杂度是O(m*n) m是主串长度n是子串的长度。

朴素模式匹配算法时间复杂度分析如下:(n为主串长度,m为模式串长度)

时间复杂度:

最好情况
O(1) 一开始就匹配成功。

最坏情况
O((n-m+1)*m) 每次不成功的匹配都发生在模式串的最后一个字符。

平均情况
O(n+m) 根据等概率原则,平均是(n+m)/2次查找。

二、KMP算法

像二进制这样的多个0和1重复的字符串,上面的模式匹配需要挨个遍历是非常慢的,KMP算法可以大大避免重复遍历的情况。

下面我们来看看KMP算法的基本原理

如上,可以看到主串S和子串T在第一轮比较的时候,前面5个相等,只有i=6和j=6的位置不等。由于子串T中abcde这5个字符本身互不相等,可以知道子串T中a就不可能和j=2、3、4、5的位置的字符相等。所以可以直接跳到i=6的位置进行比较。

再看上图,如果子串T中存在重复的元素(比如j=1,2和j=4,5处的字符),按照上面的分析,我们可以直接跳到i=4的位置比较,但是我们已经知道j=1,2和j=4,5相等,并且i=4,5和j=4,5相等,所以可以不用比较i=4,5和j=1,2。

KMP模式匹配算法就是为了不让i指针回退,既然i值不回退,我们就要考虑变化j的值了。通过上面的观察可以发现,j值的变化与主串其实没有什么关系,而是取决于子串T中是否有重复问题。

我们把T串各个位置的j值的变化定义为一个数组next,那么next的长度就是T串的长度,可以得到下面函数:

#include <stdio.h>void get_next(const char T[], int *next){int i,j;i = 1;j = 0;next[1] = 0;//T[0]是子串T的长度while(i < T[0]){//T[i]表示后缀的单个字符//T[j]表示前缀的单个字符if( j==0 || T[i] == T[j]){++i;++j;next[i] = j;}else{j = next[j];}}
}int Index_KMP(const char S[], const char T[], int pos){int i = pos;int j = 1;int next[255];get_next(T, next);while(i <= S[0] && j <= T[0]){//相对于朴素算法,增加了一个j==0的判断if( j==0 || S[i] == T[j]){++i;++j;}else{//j回退到合适的位置,i的值不变j = next[j];}}if( j>T[0]){return i-T[0];}else{return 0;}
}
int main(){return 0;
}

整个算法的时间复杂度为O(n+m)

朴素模式匹配算法和KMP匹配算法 详细相关推荐

  1. C/C++——朴素的模式匹配算法和KMP模式匹配算法

    朴素的模式匹配算法 其实就是一个一个往下匹配,没有任何优化,在好的情况下时间复杂度为O(n+m),在最求的情况下时间复杂度为O((n-m+1)*m). 代码实现: //在主串s中找子串t,若找到返回字 ...

  2. 数据结构与算法之美笔记——基础篇(下):图、字符串匹配算法(BF 算法和 RK 算法、BM 算法和 KMP 算法 、Trie 树和 AC 自动机)

    图 如何存储微博.微信等社交网络中的好友关系?图.实际上,涉及图的算法有很多,也非常复杂,比如图的搜索.最短路径.最小生成树.二分图等等.我们今天聚焦在图存储这一方面,后面会分好几节来依次讲解图相关的 ...

  3. BF算法和KMP算法

    给定两个字符串S和T,在主串S中查找子串T的过程称为串匹配(string matching,也称模式匹配),T称为模式.这里将介绍处理串匹配问题的两种算法,BF算法和KMP算法. BF算法 (暴力匹配 ...

  4. K近邻算法和KD树详细介绍及其原理详解

    相关文章 K近邻算法和KD树详细介绍及其原理详解 朴素贝叶斯算法和拉普拉斯平滑详细介绍及其原理详解 决策树算法和CART决策树算法详细介绍及其原理详解 线性回归算法和逻辑斯谛回归算法详细介绍及其原理详 ...

  5. Algorithm:C++语言实现之字符串相关算法(字符串的循环左移、字符串的全排列、带有同个字符的全排列、串匹配问题的BF算法和KMP算法)

    Algorithm:C++语言实现之字符串相关算法(字符串的循环左移.字符串的全排列.带有同个字符的全排列.串匹配问题的BF算法和KMP算法) 目录 一.字符串的算法 1.字符串的循环左移 2.字符串 ...

  6. 若S作主串,P作模式串,试分别写出利用BF算法和KMP算法的匹配过程。

    目   录 题目: 百度文库-答案: (1) (2) MOOC标准答案: (1) (2) mooc答案-截图: 数据结构(C语言版)-严蔚敏2007 题目: 设字符串S='aabaabaabaac', ...

  7. 【算法篇-字符串匹配算法】BF算法和KMP算法

    目录 前言 1. BF算法 1.1 画图分析 1.3 BF 算法的时间复杂度 2. KMP 算法 2.1 KMP 算法和 BF 算法 的区别 2.1.1 为什么主串不回退? 2. 2 next 数组 ...

  8. 数据结构之字符串匹配算法(BF算法和KMP算法)

    字符串匹配算法: 就是给定两个串,主串(s)和子串(sub), 查找子串是否在主串里面,如果找到便返回子串在主串中第一个元素的位置下标,否贼返回-1,. 在这里我 们讨论的时候主要用字符串来举例实现. ...

  9. 串的BF算法和KMP算法个人总结

    子串(模式串)的定位操作通常称作串的模式匹配 其中包含最初始的BF算法(Brute-Force)即简单匹配算法或者称作朴素的模式匹配算法,利用穷举法的思路 另一种就是改进后的KMP算法,还有对KMP算 ...

  10. 模式串匹配的BF算法和KMP算法

    KMP是三位大牛:D.E.Knuth.J.H.Morris和V.R.Pratt同时发现的.为了解决模式匹配问题,也即寻找模式串(子串)在主串中第一次出现的位置,若模式串在主串中不存在则返回-1. 简单 ...

最新文章

  1. python输出命令_Python输出各行命令详解
  2. 沃丰报告:物联网的未来
  3. python基础学习笔记2
  4. java中c/s模式传送数据
  5. 缓存穿透、缓存并发、缓存失效之思路变迁
  6. linux如何更改服务器时间格式,Linux中date命令,格式化输出,时间设置
  7. UVa 590 Always on the run(简单链式DP)
  8. matlab将程序变量写入标题,如何该这段MATLAB程序(把一个常量改成变量)
  9. 2016.10.26
  10. 常用排序算法的python实现
  11. IOS平台hosts修改
  12. [3] UI原型设计工具Pencil Project 学习系列----- 进阶
  13. 百度有啊前端框架分析(浏览器内置事件)
  14. C语言数字转扑克牌字符,C语言编程:扑克牌魔术
  15. 服务器系统要用GUID还是MBR,win7mbr和guid应该选哪一个
  16. Java 学习情况总结
  17. 数码相机(百度百科)
  18. 青岛医院计算机招聘试题及答案,2020青岛市妇女儿童医院招聘试题及答案解析...
  19. JFreeChart 生成 蜘蛛网/刻度 雷达图
  20. hibrnate教程14~Hibernate JPA注解入门

热门文章

  1. EndnoteX8教程学习(一)
  2. Linux抓包(wireshark+tcpdump)
  3. photoshop cc 2018安装破解教程
  4. 支持免费的PCB计算机辅助设计软件eagle
  5. 小白版----使用vm安装win10
  6. Matlab伯德图如何修改相频特性的角度?终于解决了!
  7. 使用python玩转dicom文件——医学图像处理工具pydicom入门教程
  8. Kvaser新品推介:一款坚固耐用的单通道CAN / CAN FD转USB接口-Kvaser U100 编码:73-30130-01173-1
  9. CPU cache侧信道攻击
  10. MacOS壁纸文件夹如何查找