KMP算法学习

一、什么是KMP算法

Knuth-Morris-Pratt 字符串查找算法(常简称为 “KMP算法”)是在一个“主文本字符串” S 内查找一个“词” W 的出现,,以此避免对以前匹配过的字符重新检查。(在原串中匹配模式串)

二、KMP演示

http://staff.ustc.edu.cn/~ypb/jpkc/flash/Find_KMP.swf

三、KMP原理

KMP是一种最常见的改进算法,它可以在匹配过程中失配的情况下,有效地多往后面跳几个字符,加快匹配速度。

在KMP算法中有个数组,叫做前缀数组,也有的叫,每一个模式串都有一个固定的next数组,,当然它描述的也是子串的对称程度,程度越高,值越大,当然之前可能出现再匹配的机会就更大。

对于next数组的理解,参见http://blog.csdn.net/yearn520/article/details/6729426#t0

[cpp] view plaincopy

  1. void SetPrefix(const char *Pattern, int prefix[])
  2. {
  3. int i;
  4. int len=strlen(Pattern);//模式字符串长度。
  5. prefix[0]=0;
  6. for(i=1; i<len; i++)
  7. {
  8. int k=prefix[i-1];
  9. //不断递归判断是否存在子对称,k=0说明不再有子对称,Pattern[i] != Pattern[k]说明虽然对称,但是对称后面的值和当前的字符值不相等,所以继续递推
  10. while( Pattern[i] != Pattern[k] && k!=0 )//例i等于14时,求prefix[14]的值
  11. k=prefix[k-1]; //继续递归
  12. if( Pattern[i] == Pattern[k])//找到了这个子对称,或者是直接继承了前面的对称性,这两种都在前面的基础上++
  13. prefix[i]=k+1;
  14. else
  15. prefix[i]=0; //如果遍历了所有子对称都无效,说明这个新字符不具有对称性,清0
  16. }
  17. prefix[0]=-1;
  18. }

四、测试小例

[cpp] view plaincopy

  1. #include <iostream>
  2. #include <cstring>
  3. #include <string>
  4. using namespace std;
  5. string sorg;
  6. string spat;
  7. int prefix[10000];
  8. int result[20];
  9. void init()
  10. {
  11. sorg="";
  12. spat="";
  13. memset(prefix,0,sizeof(int)*10000);
  14. //memset(result,0,sizeof(int)*20);
  15. }
  16. void setprefix(string temp,int next[])
  17. {
  18. int len=temp.size();
  19. next[0]=0;
  20. for(int i=1;i<len;i++)
  21. {
  22. int k=next[i-1];
  23. while(temp[k]!=temp[i]&&k!=0)
  24. k=next[k-1];
  25. if(temp[k]==temp[i])
  26. next[i]=k+1;
  27. else
  28. next[i]=0;
  29. }
  30. next[0]=-1;
  31. for(int i=0;i<len;i++)
  32. if(next[i]>=1)
  33. next[i]=next[i]-1;
  34. }
  35. int  kmp(string s1,string s2)
  36. {
  37. int number=0;
  38. int i=0;
  39. int j=0;
  40. while(i<(int)s1.size()&&j<(int)s2.size())
  41. {
  42. if(j==-1||s1[i]==s2[j])
  43. {
  44. i++;
  45. j++;
  46. }
  47. else
  48. j=prefix[j];
  49. if(j==s2.size())
  50. {
  51. i=i-j+1;
  52. j=0;
  53. number++;
  54. }
  55. }
  56. return number;
  57. }
  58. int main()
  59. {
  60. int t;
  61. cin>>t;
  62. memset(result,0,sizeof(int)*20);
  63. for(int i=0;i<t;i++)
  64. {
  65. init();
  66. //cout<<"input spat string:"<<endl;
  67. cin>>spat;
  68. //cout<<"input sorg string:"<<endl;
  69. cin>>sorg;
  70. setprefix(spat,prefix);
  71. result[i]=kmp(sorg,spat);
  72. }
  73. for(int j=0;j<t;j++)
  74. cout<<result[j]<<endl;
  75. return 0;
  76. }

时间: 2024-10-12 21:59:25

KMP算法学习的相关文章

KMP算法 学习笔记

kmp算法在很多人看来是如此的厉害,很早之前就学过了,但是各种看不懂把我拦住了,现在重新拾取,来写一下个人的学习总结. kmp看毛片算法(小甲鱼教的)(在这给小甲鱼做个广告,我个人看来小甲鱼讲的数据结构很好,很有趣.个人创业不容易,希望大家多多支持www.fishc.com小甲鱼,我跟小甲鱼素不相识,只是有用的东西大家分享) 好了言归正传. 如果你之前看过kmp算法没有看懂希望在这不要带着一种恐惧感,如果你没看过那是更好. 网上有很多详细教程,但是大部分都很啰嗦,容易把人看晕. kmp算法没有什

KMP算法学习记录----《大话数据结构》部分匹配表学习部分

如需转载,请保留本文链接. 首先先将<大话数据结构>关于KMP算法的讲解部分贴上,本文不提供下载链接,也不会将电子书作为资料留百度云,需要电子书的各位,请自行寻找电子版. 关于上述的KMP算法种的next数组的推导部分,一直不是很明白,本贴是关于上述部分的学习推导记录. 以书中字符串为例: 1|2|3|4|5|6|7|8|9| a|b|a|b|a|a|a|b|a| 0|1|1|2|3|4|2|2|3| string T = "ababaaaba"; int i = 1;j

KMP算法学习(详解)

kmp算法又称“看毛片”算法,是一个效率非常高的字符串匹配算法.不过由于其难以理解,所以在很长的一段时间内一直没有搞懂.虽然网上有很多资料,但是鲜见好的博客能简单明了地将其讲清楚.在此,综合网上比较好的几个博客(参见最后),尽自己的努力争取将kmp算法思想和实现讲清楚. kmp算法完成的任务是:给定两个字符串O和f,长度分别为n和m,判断f是否在O中出现,如果出现则返回出现的位置.常规方法是遍历a的每一个位置,然后从该位置开始和b进行匹配,但是这种方法的复杂度是O(nm).kmp算法通过一个O(

KMP算法学习&amp;总结

0.缘起 一直ym传说中的kmp算法能以最坏线性的时间复杂度搞定字符串匹配, 开始动手看才知道kmp中的K居然是Donald.E.Knuth,<计算机程序设计艺术>的作者. 好吧,继续ym…… 1.传统的字符串匹配算法 /* * 从s中第sIndex位置开始匹配p * 若匹配成功,返回s中模式串p的起始index * 若匹配失败,返回-1 */ int index(const std::string &s, const std::string &p, const int sIn

字符串匹配的BF算法和KMP算法学习

引言:关于字符串 字符串(string):是由0或多个字符组成的有限序列.一般写作`s = "123456..."`.s这里是主串,其中的一部分就是子串. 其实,对于字符串大小关系不如是否相同重要.包括密码验证.hash列等. 而字符串的存储结构有两种:顺序存储结构和链式存储结构.由于不同的字符是连在一起的,所以一般是开足够大的空间进行顺序存储,这样更符合字符串的意义. 一.BF算法实现 一种暴力的.朴素的模式匹配算法,是的,时间复杂度为O(M*N).而下面的KMP算法则是O(M+N)

KMP算法学习笔记

http://www.matrix67.com/blog/archives/115 Orz maxtix67 一直拖着到碰到了KMP算法的题才学.. 设有字符串A:abefgababef 模式串 B:abefgabef 当A与B进行匹配时,设i是A上的指针,j是B上的指针,则A和B匹配到第8位就会失配.按照常规方法,我们会将i跳回到2,j跳回到1进行匹配.观察之后我们会发现其实这是多余的,因为中间的befg都是不可能的,我们应该直接跳到A的第6位进行匹配. KMP算法就是通过过滤这样无用字符来加

字符串匹配-KMP算法学习笔记

参考文章: 1.字符串匹配的KMP算法 2.KMP算法详解 3.从头到尾彻底理解KMP 版权声明:本文为博主原创文章,未经博主允许不得转载.

KMP算法学习记录----Jake Boxer博文学习部分

如需转载,请保留本文链接. Jake Boxer 英文博文链接:http://jakeboxer.com/blog/2009/12/13/the-knuth-morris-pratt-algorithm-in-my-own-words/ 如何使用部分匹配表 1.作用:使用部分匹配表跳过那些已经做过的,旧的比较部分,从非重复匹配部分开始. 2.if(匹配表结果大于1) { 允许跳过的字符数量 = 匹配长度 - 部分匹配表[匹配长度-1]; } else { 允许跳过的字符数量 =  部分匹配表[匹

算法学习笔记 KMP算法之 next 数组详解

最近回顾了下字符串匹配 KMP 算法,相对于朴素匹配算法,KMP算法核心改进就在于:待匹配串指针 i 不发生回溯,模式串指针 j 跳转到 next[j],即变为了 j = next[j]. 由此时间复杂度由朴素匹配的 O(m*n) 降到了 O(m+n), 其中模式串长度 m, 待匹配文本串长 n. 其中,比较难理解的地方就是 next 数组的求法.next 数组的含义:代表当前字符之前的字符串中,有多大长度的相同前缀后缀,也可看作有限状态自动机的状态,而且从自动机的角度反而更容易推导一些. "前