KMP算法匹配字符串

朴素匹配算法

  字符串的模式匹配的方法刚开始是朴素匹配算法,也就是经常说的暴力匹配,说白了就是用子串去和父串一个一个匹配,从父串的第一个字符开始匹配,如果匹配到某一个失配了,就重新去从父串的下一个字符开始匹配,这样的算法虽然理解起来容易,但是算法的时间复杂度无疑是很高的,假如父串是一个很长的字符串,而字串恰恰不和父串匹配,那无疑是对CPU的迫害。

  下面贴几张图看看这种朴素匹配算法:

但是第四个出现失配,就得重新让字串去和父串的第二个字符匹配,发现第二个也不匹配,只能再次匹配第三个,如下:

  这样下来时间复杂度大大变高,但是通过上帝视角我们可以发现其实第二个完全不用试,但是计算机不知道啊,所以我们就需要一个更好的算法来解决这个问题,这个算法就是要在朴素算法的基础上额外告诉计算机哪些地方不用尝试,可能我上面的这个例子举得不太恰当,但是这个算法的额外功能就是告诉了计算机如果某个位置失配了应该去尝试哪个位置。

  

KMP算法——和计算机的友好交流

  前面我们说KMP算法其实就是告诉计算机如果某个位置失配后应该往哪个位置回溯。而这个功能的实现其实只需要一个next数组,而这个数组也恰恰是这个算法的核心所在。

next数组

  这个数组里面存储的就是字串中每个位置失配后应该回溯的下标。举个例子,比如第9个元素失配后应该回溯到第3个再次匹配尝试,那就应该是next[9] = 3,值得注意的是,我们定义的串这个数据结构一般没有0号元素,所以next数组一样,next[0]没有意义。

  next数组该如何实现呢?

比如这块我们发现1-7和9-15都相等,而8和16不相等,那如果在第16个位置发生失配,就可以用1-7依次替代9-15的位置,用第8个再去匹配,如果匹配上了就继续往下匹配,未匹配就继续回溯。

代码实现(next数组):

void get_next(string son, int* next)
{
int i = 1; //下标
int j = 0; //回去的位置
next[1] = 0;
/*因为字符串未设置0号元素,所以next从1开始,默认为0,你应该懂我意思吧,回溯到0,你可能会问:
不是说好没有0号元素吗。你想啊,让字串的0号元素和父串的下一个匹配,难道不就是让字串的第一个和父串的
下一个匹配吗*/
while (i < son.len)
{
//如果这两个相等,即下标为i和j的元素相等,则当后面那个元素即i的下一个元素失配时,回溯到j的下一个元素,因为i和j的元素相等,所以保证了前面的一致,可以回溯
if (j == 0 || getch(son, i) == getch(son, j))
{
i++; j++; //精华,++后对应上面那句注释的 “当后面那个元素即i的下一个元素失配时,回溯到j的下一个元素”
if (getch(son, i) == getch(son, j)) //这里是一处优化,如果++后还相等,那你回溯回去肯定还失配啊,就再次回溯到你回溯的回溯
next[i] = next[j];
else
next[i] = j;
}
else //如果不相等,就将j回溯,i不能变,因为i一个一个加给next数组每个依次赋值
j = next[j];
}
}

KMP算法部分

  实现了next数组,剩下的就很简单了,利用next数组在失配时去回溯就ok了。

代码实现:

getch()函数是为了随机访问串

int kmp(string far, string son)
{
int next[255];
get_next(son, next);
int index = 1; //子串的下标索引
for (int i = 1; i <= far.len; i++) //遍历父串
{
while (index <= son.len)
{
if (getch(far, i) == getch(son, index))
{
index++; //如果匹配给子串+1
if (index == son.len + 1)
{
printf("成功!\n");
return i - son.len + 1;
}
break;
}
else
{
index = next[index];
if (index == 0)
{
index = 1;
break;
}
}
}
}
printf("失败!\n");
return 0;
}

字符串模式匹配——KMP算法的更多相关文章

  1. 字符串模式匹配KMP算法

    一篇不错的博客:http://www.cnblogs.com/dolphin0520/archive/2011/08/24/2151846.html KMP字符串模式匹配通俗点说就是一种在一个字符串中 ...

  2. 数据结构4.3_字符串模式匹配——KMP算法详解

    next数组表示字符串前后缀匹配的最大长度.是KMP算法的精髓所在.可以起到决定模式字符串右移多少长度以达到跳跃式匹配的高效模式. 以下是对next数组的解释: 如何求next数组: 相关链接:按顺序 ...

  3. 字符串匹配算法——KMP算法

    处理字符串的过程中,难免会遇到字符匹配的问题.常用的字符匹配方法 1. 朴素模式匹配算法(Brute-Force算法) 求子串位置的定位函数Index( S, T, pos). 模式匹配:子串的定位操 ...

  4. 字符串模式匹配sunday算法

    文字部分转自:http://www.cnblogs.com/mr-ghostaqi/p/4285868.html 代码是我自己写的 今天在做LeetCode的时候,碰到一个写字符串匹配的题目: htt ...

  5. 『字符串模式匹配 KMP』

    字符串模式匹配 我们要先了解一下问题是什么. 模式匹配是数据结构中字符串的一种基本运算,给定一个子串,要求在某个字符串中找出与该子串相同的所有子串,这就是模式匹配. KMP 然后我们来认识一下今天的主 ...

  6. 字符串匹配算法KMP算法

    数据结构中讲到关于字符串匹配算法时,提到朴素匹配算法,和KMP匹配算法. 朴素匹配算法就是简单的一个一个匹配字符,如果遇到不匹配字符那么就在源字符串中迭代下一个位置一个一个的匹配,这样计算起来会有很多 ...

  7. [Algorithm] 字符串匹配算法——KMP算法

    1 字符串匹配 字符串匹配是计算机的基本任务之一. 字符串匹配是什么?举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串& ...

  8. 模式匹配KMP算法

    关于KMP算法的原理网上有很详细的解释,我试着总结理解一下: KMP算法是什么 以这张图片为例子 匹配到j=5时失效了,BF算法里我们会使i=1,j=0,再看s的第i位开始能不能匹配,而KMP算法接下 ...

  9. 查找字符串的 KMP 算法

    查找字符串是我们平常编程过程中经常遇到的,现在介绍一种查找字符串算法,增加程序的执行速度. 通常我们是这么写的: /* content: search a string in a othor stri ...

随机推荐

  1. git的基本使用-1

    1.git的安装 这里只介绍在 Linux 上安装. 如果你想在 Linux 上用二进制安装程序来安装 Git,可以使用发行版包含的基础软件包管理工具来安装. 如果以 Fedora 上为例,你可以使用 ...

  2. HTML_body中常用的标签部分

    meta: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <t ...

  3. FIve in a row

    Alice and Bob play 5-in-a-row game. They have a playing field of size 10 × 10. In turns they put eit ...

  4. FlyWay工作原理

    本文译自Flyway官方文档,原文地址https://flywaydb.org/getstarted/how 当你最开始将FlyWay指向一个空数据库时. 它会试着去查找schema历史表,如果此时数 ...

  5. springboot中的pom文件是如何管理依赖的

    我们来看一下新建完成后的springboot中的pom文件 <?xml version="1.0" encoding="UTF-8"?> <p ...

  6. 这道面试必问的JVM面试题70%的Java程序员会做错

    前言 聊聊JVM,一个熟悉又陌生的名词,从认识Java的第一天起,我们就会听到这个名字,在参加工作的前一两年,面试的时候还会经常被问到JDK,JRE,JVM这三者的区别. JVM可以说和我们是老朋友了 ...

  7. dart入门指南

    近来,flutter的热度在上升.flutter应用的主要开发语言是dart, 因此,欲练flutter, 必先了解dart. dart是由google开发的编程语言,可用于开发移动应用,桌面应用,h ...

  8. 多个DataTable的合并成一个新表

    多个DataTable的合并成一个新表 参考:https://www.cnblogs.com/JuneZhang/archive/2011/12/11/2284243.html

  9. Vue.js 一问一答

    Vue.js 一问一答 记录一下在学习 Vue 过程中给自己问的一些问题,持续更新中... Vue.js 的核心是什么? 官网:Vue.js 的核心是一个允许采用简洁的模板语法来声明式的将数据渲染进 ...

  10. 使用littlefs-fuse在PC端调试littlefs文件系统

    背景 littlefs是arm面向嵌入式设备推出的一款掉电安全的小型文件系统,具有抗掉电,动态磨损均衡,RAM/ROM需求少等特点,具体介绍可见 https://github.com/ARMmbed/ ...