今天又看了一遍KMP,感觉真的懂了...就来这儿发一下心得吧.

KMP算法其实就是暴力的改进版.让我们看看暴力的匹配.

  1. Original string: ababababcbbababababc
  2. Pattern string:  abababc

步骤:

  1. ababababcbbababababc
  2. abababc
    ....中间一些步骤
    ababababcbbababababc
    abababc
    这里ac匹配不了了,传统的作法会从第二个字符`b'开始匹配.明显不行又跳出.即:
    ababababcbbababababc
    a...
    再从第三个字符`a'开始:
    ababababc...
    abababc
    现在匹配了.继续重复.

很明显这个算法在极端情况下的时间复杂度是$\text{O}\left( len\left( \text{Orig String} \right) \cdot len\left( \text{Patt String}\right)\right)$.效率很低.

想一想.在Brute Force中,每次失配后都会将Pattern的头指针指向下一个字符匹配,相当于每次失配都只能跳过一个字符.显然这么做效率非常低.能不能一次跳过多个字符却依然不会漏过匹配呢?当然可以.这样跳过的要求是什么呢?

  1. 看看这个例子:
    ababababc
    abababc
    首先`a'和`c'不匹配.跳到`b'么?明显不行,不匹配.
    注意到模式串中的
    abababc
    最前面的`ab'和无法匹配的`c'前面的`ab'是相同的.那么往前跳两格.为什么不跳四格呢?注意到
    abababc
    中,最前面也有`abab'.
    原因是这两部分长度的和超过了已经匹配的字符串的长度,便也许会漏解.
    那么在这时设置一个`f[i]'数组,表示第i位匹配失败后将i减小到几.
    那么在这个例子中,`f[i]'值如下:(虚拟一个`s[i]'数组表示跳多远)
    patt a b a b a b c
    f[i] 0 0 0 1 2 3 0
    s[i] 0 1 2 2 2 2 6
    i 0 1 2 3 4 5 6
    即s[i]=i-f[i]
    那么如何求这个f数组呢?

这就是一个有意思的问题了.注意到模式串一般来说要比查找的串要短不少,因此用暴力的$\text{O}\left( n^2\right)$也算一种减小问题规模的算法.但是这样就不统一了,这个时间复杂度奇怪得很.注意到求这个数组的过程神似字符串匹配,那么我们可以用KMP自己来求解,即考察所有在它前面的字符中能够匹配的最大的串.这个可以用一种类似于动归的办法很方便的求解.

设已经求到第i位,那么第i+1位就能被方便的求解.(伪代码,p是模式串,下标从0开始)

  1. f[0]=f[1]=0
    j=f[i]
    while j && p[i]!=p[j]:
    j=f[j]
    f[i+1]=j+1 if p[i]==p[j] or 0

最后附上代码

  1. #include <string.h>
  2. #include <malloc.h>
  3. #include <stdio.h>
  4. void getfail(char* p,int* f){
  5. int m=strlen(p),i=1,j;
  6. f[0]=f[1]=0;
  7. for(;i<m-1;++i){
  8. j=f[i];
  9. while(j&&p[i]!=p[j]){
  10. j=f[j];
  11. }
  12. f[i+1]=(p[i]==p[j]?++j:0);
  13. }
  14. }
  15. int match(char* s,char* p,int* res){
  16. int l=strlen(s),i,j,lp=strlen(p),lm=0;
  17. int* f=(int*)malloc((lp+10)*sizeof(int));
  18. if(f==NULL) return -2;
  19. getfail(p,f);
  20. j=0;
  21. for(i=0;i<l;++i){
  22. while(j&&p[j]!=s[i]) j=f[j];
  23. if(p[j]==s[i]) ++j;
  24. if(j==lp){
  25. res[lm]=i-lp+1;
  26. ++lm;
  27. j=f[j-1];
  28. if(p[j]==s[i]) ++j;
  29. }
  30. }
  31. return lm;
  32. }

这段代码可以求出所有匹配字符串,并返回匹配数.

KMP算法心得的更多相关文章

  1. 学习KMP算法的一点小心得

    KMP算法应用于 在一篇有n个字母的文档中 查找某个想要查找的长度为m的单词:暴力枚举:从文档的前m个字母和单词对比,然后是第2到m+1个,然后是第3到m+2个:这样算法复杂度最坏就达到了O(m*n) ...

  2. 很详尽KMP算法(厉害)

    作者:July时间:最初写于2011年12月,2014年7月21日晚10点 全部删除重写成此文,随后的半个多月不断反复改进.后收录于新书<编程之法:面试和算法心得>第4.4节中. 1. 引 ...

  3. 子字符串查找之————关于KMP算法你不知道的事

    写在前面: (阅读本文前需要了解KMP算法的基本思路.另外,本着大道至简的思想,本文的所有例子都会做从头到尾的讲解) 作者翻阅了大量网上现有的KMP算法博客,发现广为流传的竟然是一种不完整的KMP算法 ...

  4. KMP算法 字符串匹配(看猫片)

    前言 此篇笔记根据自己的理解和练习心得来解释算法,只代表个人观点,如有不足请指出(我刚学QWQ) 浅谈字符串匹配 设想一个场景,假设你是一个净化网络语言环境的管理员,每天需要翻阅大量的文章和帖子来查找 ...

  5. 简单有效的kmp算法

    以前看过kmp算法,当时接触后总感觉好深奥啊,抱着数据结构的数啃了一中午,最终才大致看懂,后来提起kmp也只剩下“奥,它是做模式匹配的”这点干货.最近有空,翻出来算法导论看看,原来就是这么简单(先不说 ...

  6. KMP算法

    KMP算法是字符串模式匹配当中最经典的算法,原来大二学数据结构的有讲,但是当时只是记住了原理,但不知道代码实现,今天终于是完成了KMP的代码实现.原理KMP的原理其实很简单,给定一个字符串和一个模式串 ...

  7. 萌新笔记——用KMP算法与Trie字典树实现屏蔽敏感词(UTF-8编码)

    前几天写好了字典,又刚好重温了KMP算法,恰逢遇到朋友吐槽最近被和谐的词越来越多了,于是突发奇想,想要自己实现一下敏感词屏蔽. 基本敏感词的屏蔽说起来很简单,只要把字符串中的敏感词替换成"* ...

  8. KMP算法实现

    链接:http://blog.csdn.net/joylnwang/article/details/6778316 KMP算法是一种很经典的字符串匹配算法,链接中的讲解已经是很明确得了,自己按照其讲解 ...

  9. 数据结构与算法JavaScript (五) 串(经典KMP算法)

    KMP算法和BM算法 KMP是前缀匹配和BM后缀匹配的经典算法,看得出来前缀匹配和后缀匹配的区别就仅仅在于比较的顺序不同 前缀匹配是指:模式串和母串的比较从左到右,模式串的移动也是从 左到右 后缀匹配 ...

随机推荐

  1. MOTT的学习(一)

    MQTT的消息体 flag 此标志设置时,客户端或服务器尝试重新publish,PUBREL,subcribe或unsubscribe消息.这适用于消息, 其中的QoS的值大于零(0),并且需要确认. ...

  2. Convention插件

    考虑使用COnvention插件可以进行零配置而且插件进行很多规范的约定也可以对开发合作当中按着它相应的规律开发..感觉也挺方便管理的.下面简单介绍它的使用. 首先我们需要使用到的jar包: Java ...

  3. OC基础--分类(category) 和 协议(protocol)

    OC 中的category分类文件相当于 C#中的部分类:OC 中的protocol协议文件(本质是头文件)相当于 C#中的接口.今天就简单说明一下OC中的这两个文件. 由于视频中的Xcode版本低, ...

  4. Spring-事物的隔离级别

    Spring中定义了5中不同的事务隔离级别: 1. ISOLATION_DEFAULT(一般情况下使用这种配置既可) ; 这是一个PlatfromTransactionManager默认的隔离级别,使 ...

  5. selenium ide 录制回放link链接报错

    回放是出现以下错误: 也就是回放点击打开新的链接时出现这个错误, 这个问题说的是 点击此链接会新打开一个窗口 selenium1是不支持多窗口切换的 因此会卡在这里,也就录制不支持这个操作,但是很多书 ...

  6. json2.js的初步学习与了解

    json2.js的初步学习与了解,想要学习json的朋友可以参考下. json2.js的初步学习与了解 1.)该js的下载地址是:http://www.json.org/json2.js 2.)在页面 ...

  7. 【kAriOJ】离散数学春季学期编程测试 1

    A.凯撒密码 题意: 给你k1,k2,和一串明文,一串密文. 明文用k1加密,密文用k2解密. 对于明文要把字母转换成大写字母,非字母全部删除. 额:要考虑到取模可能会变成负数,所以要加一下26再取模 ...

  8. 【BZOJ-1406】密码箱 约数 + 乱搞 + set?

    1406: [AHOI2007]密码箱 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1143  Solved: 677[Submit][Status][ ...

  9. 【BZOJ】【1009】 【HNOI2008】GT考试

    DP/KMP/矩阵乘法 好神的题啊……跪了跪了 $n\leq 10^9$是什么鬼……我们还是先不要考虑这个鬼畜的玩意了>_> 用类似数位DP的思路,我们可以想到一个DP方程:$f[i][j ...

  10. 微信支付(APP)集成时碰到的问题(.net提示“无权限”、iOS跳转到微信支付页面中间只有一个“确定”按钮)

    直入主题之前,请容我吐槽一下微*的官方东西:ASDFQ%#$%$#$%^FG@#$%DSFQ#$%.......:吐槽玩了!大家心照就好. 要完成手机APP跳转到微信的APP进行微信支付,需要进行如下 ...