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. Python ——selenium报错 'chromedriver.exe' executable needs to be in PATH

    from selenium import webdriver dr = webdriver.Chrome() 运行时报错: 问题分析: 1.没有下载chromedriver.exe 2.chromed ...

  2. 将object转换成dyamic类型 解决long输出到浏览器过长精度丢失问题

    需求: 数据库使用飘雪算法保存唯一标识  是一个18位长整形 将数据输出到浏览器时出现了精度丢失问题,这是一个重大的BUG.如果没解决好整个项目都要改一遍. 讨论有三个办法 1.把所有实体 数据模型的 ...

  3. Postman 关联接口测试(带有token鉴权)

    Postman 关联接口测试(带有token鉴权) 一.登陆接口 创建一个request请求 在Tests中添加JavaScript代码,用来获取鉴权 pm.test("V2", ...

  4. ES6中export default与export的区别

    1.export default 和export都可以用于导出常量,函数,文件,模块等: 2.可以在模块中通过import+(常量 | 函数 | 文件 | 模块)名的方式,将其导入,以便能够对其进行使 ...

  5. 输出错误long类型

    Microsoft Visual C++ 输出不了long 类型的数字怎么办? 在C/C++中,64为整型一直是一种没有确定规范的数据类型.现今主流的编译器中,对64为整型的支持也是标准不一,形态各异 ...

  6. BBS项目知识点汇总

    目录 bbs项目知识点汇总 一. JavaScript 1 替换头像 2 form表单拿数据 3 form组件error信息渲染 4 添加html代码 5 聚焦操作 二 . html在线编辑器 三 . ...

  7. MySQL创建数据表时设定引擎MyISAM/InnoDB

    我在配置mysql时将配置文件中的默认存储引擎设定为了InnoDB.今天查看了MyISAM与InnoDB的区别,在该文中的第七条"MyISAM支持GIS数据,InnoDB不支持.即MyISA ...

  8. 用js写直角三角形,等腰三角形,菱形

    //一. 画一个直角三角形     // 第几行   *号数     // *        1        1       // **       2        2     // ***    ...

  9. 为什么使用HTTP2?

    最近我们公司的官网由原来的http1.1已升级到http2,而我们前端开发对http2还是一片懵懂,更不知道为何换成了这个,故此补充了下http2的相关知识. http1.1相比于http1.0有哪些 ...

  10. 01-EF Core笔记之创建模型

    使用EF Core的第一步是创建数据模型,模型建的好,下班走的早.EF Core本身已经设置了一系列约定来帮我们快速的创建模型,例如表名.主键字段等,毕竟约定大于配置嘛.如果你想改变默认值,很简单,E ...