// 此博文为迁移而来,写于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. Linux & Oracle 安装目录说明

    http://blog.itpub.net/9399028/viewspace-775297/

  2. 无废话Android之listview入门,自定义的数据适配器、采用layoutInflater打气筒创建一个view对象、常用数据适配器ArrayAdapter、SimpleAdapter、使用ContentProvider(内容提供者)共享数据、短信的备份、插入一条记录到系统短信应用(3)

    1.listview入门,自定义的数据适配器 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/and ...

  3. C语言的OOP实践(OOC)

    OOC 面向对象 C 语言编程实践 - 文章 - 伯乐在线http://blog.jobbole.com/105105/ ---硬着头皮看完了,但是感觉还是抽象有不理解的地方,感觉用C实现OOP好难啊 ...

  4. BAT批量处理 命令

    第一章 批处理基础第一节 常用批处理内部命令简介 批处理定义:顾名思义,批处理文件是将一系列命令按一定的顺序集合为一个可执行的文本文件,其扩展名为BAT或者CMD.这些命令统称批处理命令.小知识:可以 ...

  5. Oracle 11g新特性 -- 延迟段

    11gR2之前的版本中,当创建一张表时,会自动分配段空间,这样做有几个弊端: 1. 初始创建表时就需要分配空间,自然会占用一些时间,如果初始化多张表,这种影响就被放大. 2. 如果很多表开始的一段时间 ...

  6. C++中的链接错误

    1.有可能是类的函数实现的时候错误. 如:应该为MVT_PAR1* GpsTcpCallback::GetMUT_PAR1(unsigned char* data,int i), 却写成了MVT_PA ...

  7. 应用程序调试工具gdb,王明学learn

    应用程序调试工具gdb学习使用 一.GDB简介 GDB 是 GNU 发布的一款功能强大的程序调试工具.GDB 主要完成下面三个方面的功能: 1.启动被调试程序. 2.让被调试的程序在指定的位置停住. ...

  8. V for Vendetta

    V for Vendetta V字仇杀队 复仇者V 安迪·沃卓斯基 and Larry Wachowski 思想,是最强大的武器.因为,世界上的独裁政府,有一个共同特点就是推行洗脑和愚民政策. 经典台 ...

  9. whl文件安装

    进入whl文件的目录,直接pip install ...即可

  10. 汇编指令CLI/STI

    CLI禁止中断发生STL允许中断发生 这两个指令只能在内核模式下执行,不可以在用户模式下执行:而且在内核模式下执行时,应该尽可能快的恢复中断,因为CLI会禁用硬件中断,若长时间禁止中断会影响其他动作的 ...