// 此博文为迁移而来,写于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. 二叉树学习笔记之经典平衡二叉树(AVL树)

    二叉查找树(BSTree)中进行查找.插入和删除操作的时间复杂度都是O(h),其中h为树的高度.BST的高度直接影响到操作实现的性能,最坏情况下,二叉查找树会退化成一个单链表,比如插入的节点序列本身就 ...

  2. Linux 配置NFS,文件共享

    配置:   1.设定共享主机服务器    ---(注意防火墙) 编辑ipA端的/etc/exports 文件 [root@dbrac2 ~]# cat /etc/exports /media  192 ...

  3. Java Hour 64 JVM 最大内存设置

    从这篇博文起,不再是流水式的学习记录了,稍微改进下风格. 运行时获得当前JVM 设置大小 首先,-Xmx100000000指定最大的内存分配. public static void main(Stri ...

  4. mysql无法远程连接的解决方法

        在阿里云服务器上安装好MySQL后,首先想到的就是安装一款工具来管理数据库,一开始选择了phpMyAdmin,这个工具安装很简单,只要解压到能访问的目录下就行了.在浏览器中访问phpMyAdm ...

  5. 高效jQuery的奥秘

    讨论jQuery和javascript性能的文章并不罕见.然而,本文我计划总结一些速度方面的技巧和我本人的一些建议,来提升你的jQuery和javascript代码.好的代码会带来速度的提升.快速渲染 ...

  6. hdu 5833 Zhu and 772002 高斯消元

    Zhu and 772002 Problem Description Zhu and 772002 are both good at math. One day, Zhu wants to test ...

  7. HDU 5787 K-wolf Number 数位DP

    K-wolf Number Problem Description   Alice thinks an integer x is a K-wolf number, if every K adjacen ...

  8. Linux之find命令用于统计信息

    1. 计算当前目录中的文件数: [root@localhost tmp]# find . -type f | wc -l 2. 查找/etc目录中最新的和最旧的文件,以文件时间排序并按年-月-日的格式 ...

  9. 深入理解KMP算法之续篇

    前言: 纠结于KMP已经两天了,相较于本人之前博客中提到的几篇博文,本人感觉这篇文章更清楚地说明了KMP算法的来龙去脉. http://www.cnblogs.com/goagent/archive/ ...

  10. java gui 之容器组件

    演示Frame和Panel package unit7; import java.awt.*; public class SimpleFrame { public static void main(S ...