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

UPDATE(20200316):重写介绍(五年前好像什么都没写一样)。

1、前言

  好吧我得承认这东西应该是早就要会了的。。。虽然感觉上用的不多,但是当我开始接触AC自动机的时候,发现这是一个很必要的知识点,所以今天来讲一讲。
  然而有一个问题了——为什么我一直没有搞懂就是因为许多许多次我看网上的一些文章就发现总是弄得很复杂,所以我推荐大家直接看代码,更容易弄懂。反正我就这么明白了。在AC自动机明白之后,将会有更详细地阐述。

2、介绍

  KMP算法,是在普通字符串匹配算法的基础上改进的算法,核心在于:利用每次匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。首先我们先看看普通匹配算法的思路:假设读入a, b两个字符串,a为主串,b为模式串。从a的第一位起,与b的第一位起逐位匹配,直到匹配到模式串串尾。如果出现不匹配情况,则退出该次匹配,从a的第二位起,与b的第一位起逐位匹配,以此类推,即最坏匹配复杂度为O(a.len * b.len)。

  KMP算法引入一个新的数组:fail数组,表示b的第i位起的子串与b本身串的最长前缀长度。例如:

同样地,你也可以理解为表示b的前i位子串的公共前后缀长度(即前缀和后缀相同)

预处理出fail数组的意义是什么?前面提到了,每次匹配失败,我们都需要从主串第一位重新来过。

再来看一个例子,如图所示,在匹配过程中匹配到第6位时,我们发现匹配失败了;而已匹配上的前5位,其第5位的fail值为3,表示前5位的公共前后缀长度为3,也就是说,[3, 5]子串和[1, 3]子串是一致的,那我们也就不再需要对这一段进行一一匹配了,从而直接从a的第5+1=6位和b的第3+1=4位开始匹配。

以此类推,可以理解为b串自身整体右移,使其与a串匹配,故时间复杂度约为O(a.len + b.len),大幅降低。

3、代码

 #include <bits/stdc++.h>
using namespace std; #define MAXN 100005 int la, lb, fail[MAXN];
char a[MAXN], b[MAXN]; int main() {
cin >> a + >> b + ;
la = strlen(a + ), lb = strlen(b + );
fail[] = -;
for (int i = , x = -; i <= lb; i++) {
while (x >= && b[x + ] != b[i]) x = fail[x];
fail[i] = ++x;
}
for (int i = , x = ; i <= la; i++) {
while (x >= && b[x + ] != a[i]) x = fail[x];
if (++x == lb) cout << i - lb + , exit();
}
cout << "N/A";
return ;
}

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

  1. KMP算法简明扼要的理解

    KMP算法也算是相当经典,但是对于初学者来说确实有点绕,大学时候弄明白过后来几年不看又忘记了,然后再弄明白过了两年又忘记了,好在之前理解到了关键点,看了一遍马上又能理解上来.关于这个算法的详解网上文章 ...

  2. KMP算法简明法则

    KMP算法也算是相当经典,但是对于初学者来说确实有点绕,大学时候弄明白过后来几年不看又忘记了,然后再弄明白过了两年又忘记了,好在之前理解到了关键点,看了一遍马上又能理解上来.关于这个算法的详解网上文章 ...

  3. 串匹配问题 (KMP算法) 详解

    串这个概念对于我们学到现在的水平来说应该是经历颇丰了,因为在C语言中我们所用到的"串"知识是在字符串那里,有了这个概念,我们再去学习串就相对而言轻松多了. 那么,现在来介绍一下字符 ...

  4. 简单有效的kmp算法

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

  5. KMP算法

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

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

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

  7. KMP算法实现

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

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

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

  9. 扩展KMP算法

    一 问题定义 给定母串S和子串T,定义n为母串S的长度,m为子串T的长度,suffix[i]为第i个字符开始的母串S的后缀子串,extend[i]为suffix[i]与字串T的最长公共前缀长度.求出所 ...

随机推荐

  1. 知乎大牛的关于JS解答

    很多疑惑一扫而空.... http://www.zhihu.com/question/35905242?sort=created JS的单线程,浏览器的多进程,与CPU,OS的对位. 互联网移动的起起 ...

  2. IReport问题整理

    1. 问题:IReport如何实现变量字段$F{ propertyName}赋值为一个NULL对象时不显示”null”, 而显示为空白? 解决方法:选中动态单元格,右键选择属性,在弹出对话框TextF ...

  3. sqlplus使用(二)

    详见SQL*Plus® User's Guide and Reference Release 11.2   5 Using Scripts in SQL*Plus   1.定义环境变量 _EDITOR ...

  4. Jenkins搭建

    1.添加仓库: sudo wget -O /etc/yum.repos.d/jenkins.repo \ http://jenkins-ci.org/redhat/jenkins.repo sudo ...

  5. gdb optimized out错误解决

    转自:http://blog.csdn.net/cws1214/article/details/12023093 when linux gdb debug, print a variable, suc ...

  6. C语言里面捕获错误机制

    在C语言中异常处理一般有这么几种方式: 1.使用标准C库提供了abort()和exit()两个函数,它们可以强行终止程序的运行,其声明处于<stdlib.h>头文件中. 2.使用asser ...

  7. 如何解决虚拟机Mac OS X 不支持二进制编译问题()

    本文将着重解决在使用VMware 11安装Mac OS虚拟机出现”Mac OS X 不支持二进制编译.若要运行 Mac OS X 主机上需要一个 VMware Workstation 支持英特尔 VT ...

  8. pythonchallenge之C++学习篇-01

    字符处理时每个语言都具备的一种功能,其中还有一些语言因此出名,比如perl,shell,还有一些函数式的编程语言 C语言中的字符串与数组和指针联系的比较紧密,因此可以这样生命字符串*p="h ...

  9. 浅谈JSON.parse()、JSON.stringify()和eval()的作用

    (1)JSON.parse 函数 var json = '{"name":"GDT","age":23,"University&q ...

  10. Linux学习笔记(7)Linux常用命令之压缩解压命令

    (1)gzip gzip命令用于压缩文件,英文原意为GNU zip,所在路径/bin/gzip,其语法格式为: gzip [文件] 压缩后的文件格式为.gz. 例:将/etc目录下的services文 ...