[知识点]KMP算法

// 此博文为迁移而来,写于2015年5月24日,不代表本人现在的观点与看法。原始地址:http://blog.sina.com.cn/s/blog_6022c4720102w1iw.html

1、前言

好吧我得承认这东西应该是早就要会了的。。。虽然感觉上用的不多,但是当我开始接触AC自动机的时候,发现这是一个很必要的知识点,所以今天来讲一讲。

然而有一个问题了——为什么我一直没有搞懂就是因为许多许多次我看网上的一些文章就发现总是弄得很复杂,所以我推荐大家直接看代码,更容易弄懂。反正我就这么明白了。在AC自动机明白之后,将会有更详细地阐述。

2、fail数组

KMP算法,是在O(n2)普通字符串匹配基础上的一个改进版本,KMP算法的关键是利用每次匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。若读入s1,s2两个字符串(s1.len最最核心的部分在于读入s1串的时候,利用一个fail[ ](也可以命名为next[ ])数组,其包含了模式串的局部匹配信息。这就是很多地方讲的很多很复杂的地方。所以说如果你想清楚透彻地搞懂这个数组存在的意义,还是推荐你去看其他人的博文,很详细。用我简单的话来讲,fail[i]表示s1的第i位起的后面部分子串与s1本身整个串的最长前缀个数。举几个生动的例子:

1、“hellohehhelaa“    fail[ ]={0,0,0,0,0,1,2,1,1,2,3,0,0}

2、“helloworldhowareyou“    fail[ ]={0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}

3、“bowbowbowbowb“    fail[ ]={0,0,0,1,2,3,4,5,6,7,8,9,10}

4、“refrigerator“    fail[ ]={0,0,0,1,0,0,0,1,0,0,0,1}

这个步骤我们在进行匹配之前将其处理好。

3、利用fail匹配

得到了fail数组,接着就要匹配了。我们的fail数组作用就在于每一次匹配失败之后不要又分别从s1,s2开头匹配,那样就是传说中的O(n2)算法了。根据之前得到的信息,我们可以跳过一些绝对匹配不上的字符以减低复杂度。

4、代码

----------------------------------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#define MAXN 205

int fail[MAXN],temp,la,lb;
char s1[MAXN],s2[MAXN];

int main()
{

freopen("KMP.in","r",stdin);
         freopen("KMP.out","w",stdout);
         scanf("%s",s1+1); la=strlen(s1+1);
         scanf("%s",s2+1); lb=strlen(s2+1);
         fail[0]=-1;
         for (int i=1;i<=la;i++)
         {
                 temp=fail[i-1];
                 while (temp!=-1 && s1[temp+1]!=s1[i]) temp=fail[temp];
                 fail[i]=temp+1;

}
         temp=0;
         for (int i=1;i<=lb;i++)
         {
                 while (temp!=-1 && s1[temp+1]!=s2[i]) temp=fail[temp];
                 temp++;
                 if (temp>=la) { printf("YES\n"); return 0; }
         }
         printf("NO\n");

return 0;
}

----------------------------------------------------------------------------------------------------

时间: 2024-11-11 01:49:24

[知识点]KMP算法的相关文章

KMP算法简明扼要的理解

KMP算法也算是相当经典,但是对于初学者来说确实有点绕,大学时候弄明白过后来几年不看又忘记了,然后再弄明白过了两年又忘记了,好在之前理解到了关键点,看了一遍马上又能理解上来.关于这个算法的详解网上文章可以说遍地开花,可我觉得大多数文章,不需要看内容,光看看详解的文章篇幅就可以吓死人,然后讲来讲去内容也让人云里雾里.我在这里结合自己的理解,简单的解释一下. 在读这篇文章之前,首先请忘记以前了解的关于KMP算法的任何知识点.因为关于有些文章的解释还不一样,可能会让本来就很绕的说法变得更绕,与其说哪样

KMP算法详细理解

KMP算法详细理解 从昨天开始看KMP算法到今天凌晨..... 把一些知识点进行总结,其实KMP还是挺简单的(HHHHHH) 博客新地址:https://miraitowa2.top/ 1:BF(暴力匹配)算法 假设现在我们面临这样一个问题:有一个文本串S,和一个模式串P,现在要查找P在S中的位置,怎么查找呢? 如果用暴力匹配的思路,并假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置,则有: 如果当前字符匹配成功(即S[i] == P[j]),则i++,j++,继续匹配下一个字符: 如

hiho 1015 KMP算法 &amp;&amp; CF 625 B. War of the Corporations

#1015 : KMP算法 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一只河蟹,于是河蟹就向小Hi和小Ho提出了那个经典的问题:“小Hi和小Ho,你们能不能够判断一段文字(原串)里面是不是存在那么一些……特殊……的文字(模式串)?” 小Hi和小Ho仔细思考了一下,觉得只能想到很简单的做法,但是又觉得既然河蟹先生这么说了,就

KMP算法详解

这几天学习kmp算法,解决字符串的匹配问题,开始的时候都是用到BF算法,(BF(Brute Force)算法是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符;若不相等,则比较S的第二个字符和T的第一个字符,依次比较下去,直到得出最后的匹配结果.BF算法是一种蛮力算法.)虽然也能解决一些问题,但是这是常规思路,在内存大,数据量小,时间长的情况下,还能解决一些问题,但是如果遇到一些限制时间和内存的字符串问

KMP算法

1 /* next数组是KMP算法的关键,next数组的作用是:当模式串T和主串S失配 2 * ,next数组对应的元素指导应该用T串中的哪一个元素进行下一轮的匹配 3 * next数组和T串相关,和S串无关.KMP的关键是next数组的求法. 4 * 5 * ——————————————————————————————————————————————————————————————————— 6 * | T | 9 | a | b | a | b | a | a | a | b | a | 7

KMP算法解决字符串出现次数

比如主串为:"1001110110" 子串为:"11" 则出现位置分别为:3 4 7 //KMP算法 2015.6.7 #include<iostream> #include<stdlib.h> using namespace std; int main() { char *s = "1001110110"; char *p = "11"; int ar[20] = { 0 }; //next ar[0

串模式匹配之BF和KMP算法

本文简要谈一下串的模式匹配.主要阐述BF算法和KMP算法.力求讲的清楚又简洁. 一 BF算法 核心思想是:对于主串s和模式串t,长度令为len1,len2,   依次遍历主串s,即第一次从位置0开始len2个字符是否与t对应的字符相等,如果完全相等,匹配成功:否则,从下个位置1开始,再次比较从1开始len2个字符是否与t对应的字符相等.... BF算法思路清晰简单,但是每次匹配不成功时都要回溯. 下面直接贴代码: int BF_Match(char *s, char *t) { int i=0,

跳跃表,字典树(单词查找树,Trie树),后缀树,KMP算法,AC 自动机相关算法原理详细汇总

第一部分:跳跃表 本文将总结一种数据结构:跳跃表.前半部分跳跃表性质和操作的介绍直接摘自<让算法的效率跳起来--浅谈"跳跃表"的相关操作及其应用>上海市华东师范大学第二附属中学 魏冉.之后将附上跳跃表的源代码,以及本人对其的了解.难免有错误之处,希望指正,共同进步.谢谢. 跳跃表(Skip List)是1987年才诞生的一种崭新的数据结构,它在进行查找.插入.删除等操作时的期望时间复杂度均为O(logn),有着近乎替代平衡树的本领.而且最重要的一点,就是它的编程复杂度较同类

字符串的KMP算法替换

1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 6 7 class myString 8 { 9 private: 10 string mainstr; 11 int size; 12 void GetNext(string p,int next[]); 13 int KMPFind(string p,int next[]); 14 public: 15 myString(); 16 //~myS