博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
KMP瞎扯一下
阅读量:4702 次
发布时间:2019-06-09

本文共 2283 字,大约阅读时间需要 7 分钟。

什么是KMP

KMP俗称看毛片算法,是高效寻找匹配字串的一个算法

百度百科

KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。

总的来说这个东西是一个加速优化的算法,而且这三个大佬能发现这个算法实在是太强大了!!!

怎么实现KMP?

next数组的实现(失配数组)

具体高大上的来说就是什么字串的前缀和和后缀和相等的最大长度,实际上这个东西就是寻找如果匹配失效怎么高速寻找下一个位置的数组。具体来说就像是一个规律一样。

具体代码

//我们规定next数组回溯如果为0,那么就是不存在。而且原字符串数组也是从第一位开始的,也就是说原字符串数组的位数跟数组的下标是一致的。  //所以说next数组回溯寻找的位置就是数组下标的位置  for(int i=2;i<=lb;i++)//i=1的时候默认回溯的就是0,所以从i=2开始寻找  {    while(j&&b[i]!=b[j+1])//j!=0的意思是j如果回溯到0的话不要让j再继续回溯,第二个条件就是自己匹配自己,这个地方是一个规律性的写法,可以自己手写模拟一下,十分的巧妙    j=next[j];//如果匹配失败,回溯到之前的位置继续匹配,而不是直接从0开始。这也是一个优化    if(b[i]==b[j+1])//如果匹配成功,j就加一继续继续寻找    j++;    next[i]=j;//每一次都得记录next数组的回溯位置  }

匹配的实现(应用next数组)

具体的代码

j=0;//j从第0位开始  for(int i=1;i<=la;i++)//因为上面已经说过数组的字符位数就是字符串数组的第几位所以从1开始循环  {    while(j&&a[i]!=b[j+1])//如果失配回溯j,进行高效的寻找    j=next[j];    if(a[i]==b[j+1])//如果匹配成功就让j++    j++;    if(j==lb)//如果j等于原先字串的长度那么就算匹配成功    {      cout<
<<"\n";//别忘记i也在一直循环++ j=next[j];//回溯到之前的位置 } }

完整代码(模板题 洛谷P3375 【模板】KMP字符串匹配)

#include 
using namespace std;int next[1000010];char a[1000010];char b[1000010];int main(){ ios::sync_with_stdio(0);//关闭同步三步走 cin.tie(0);cout.tie(0); cin>>a+1>>b+1;//从第一位输入 int la=strlen(a+1);//计算长度 int lb=strlen(b+1); int j=0;//定义j //我们规定next数组回溯如果为0,那么就是不存在。而且原字符串数组也是从第一位开始的,也就是说原字符串数组的位数跟数组的下标是一致的。 //所以说next数组回溯寻找的位置就是数组下标的位置 for(int i=2;i<=lb;i++)//i=1的时候默认回溯的就是0,所以从i=2开始寻找 { while(j&&b[i]!=b[j+1])//j!=0的意思是j如果回溯到0的话不要让j再继续回溯,第二个条件就是自己匹配自己,这个地方是一个规律性的写法,可以自己手写模拟一下,十分的巧妙 j=next[j];//如果匹配失败,回溯到之前的位置继续匹配,而不是直接从0开始。这也是一个优化 if(b[i]==b[j+1])//如果匹配成功,j就加一继续继续寻找 j++; next[i]=j;//每一次都得记录next数组的回溯位置 } j=0;//j从第0位开始 for(int i=1;i<=la;i++)//因为上面已经说过数组的字符位数就是字符串数组的第几位所以从1开始循环 { while(j&&a[i]!=b[j+1])//如果失配回溯j,进行高效的寻找 j=next[j]; if(a[i]==b[j+1])//如果匹配成功就让j++ j++; if(j==lb)//如果j等于原先字串的长度那么就算匹配成功 { cout<
<<"\n";//别忘记i也在一直循环++ j=next[j];//回溯到之前的位置 } } for(int i=1;i<=lb;i++)//这里是输出next数组的 cout<
<<" "; return 0;//结束}

总结

对于朴素的BF算法来说,从时间复杂度O(mn)降低到了O(m+n),之后还KMP的拓展算法,等以后在补坑了例如sunday算法,不过对于能发现这个算法的人来说,实在是太强大了

转载于:https://www.cnblogs.com/baccano-acmer/p/9945221.html

你可能感兴趣的文章
简易版cnlog
查看>>
erlang程序运行的几种方式
查看>>
堆heap和栈Stack(百科)
查看>>
html5页面实现点击复制功能
查看>>
633. 寻找重复的数
查看>>
沉淀,再出发:python中的pandas包
查看>>
Rule 12: Remove Duplicate Scripts(Chapter 12 of High performance Web Sites)
查看>>
操作redis数据库 & 操作Excel & 开发接口
查看>>
framework7 点取消后还提交表单解决方案
查看>>
JAVA Axis2调用WebService
查看>>
js学习---常用的内置对象(API)小结 :
查看>>
付费版百度指数 就是这么坑爹
查看>>
uva 116 Unidirectional TSP【号码塔+打印路径】
查看>>
关于android的2.2与4.4的文件读取的一点发现
查看>>
关于MAC的pkg和mpkg的分别
查看>>
11. 尽可能减少DB2的SQL请求
查看>>
MVC图片上传
查看>>
Hive优化(转)
查看>>
Android获取服务器Json字符串并显示在ListView上面
查看>>
4-13 杂记
查看>>