一、问题


  咱们先不管什么KMP,来看看怎么匹配两个字符串。

  问题:给定两个字符串,求第二个字符串是否包含于第一个字符串中。

  为了具体化,我们以 ABCAXABCABCABX 与 ABCABCABX为例。

正所谓:暴力出奇迹,枚举是真知。(大雾)先把代码敲出来再说,后面的事后面再考虑。

暴力/朴素匹配:时间复杂度O(N*M)

  虽然能够得到结果,但是速(bi)度(ge)太低。多看几遍就觉得这里出现了太多无用的计算,每次匹配失败就移动一格,实在挤牙膏。

  如果我们在每次匹配失败时多移动几位?

二、加速


KMP匹配:时间复杂度O(N+M)

  每次移动多一点,匹配速度快一点。在已经匹配过的字符串中,上面有部分的字符串与下面字符串的前面几个元素相同。

  利用已知字符,减少移动次数,比较未知字符,加快匹配速度。(KMP算法的思想)

  在每次的匹配中,已匹配的字符总是与下面字符串的前面部分(前缀)相同,又与上面字符串已匹配过的部分后面(后缀)相同。可以完全匹配的字符串都在下面的字符串中(废话)。

  因为只有每次匹配失败的时候才需要移动字符串,因此我们用一个fail/next/爱叫啥叫啥数组来记录移动的终点(下标)。

三、fail/next/爱叫啥叫啥数组


  开辟一个fail数组,fail[i]表示在匹配word[i]失败时,i需要跳转前往的下标。

  fail[i]也可表示word[0]~word[i-1]的最长公共前缀后缀长度。

  如果i跑到-1则表示:word字符串不想与你说话并把你踢出了队伍。

  来个循环,不断寻找自己的最长公共前缀后缀。由前面的匹配确定后面的fail数组的值,匹配失败直接使用fail数组(已确定的fail值)。

    "ABCA" 最长公共前缀后缀长度为1,即"A"。

    "ABCABC" 的最长公共前缀后缀长度为3,即"ABC"。

    ………………

 void setFail(){
int i = , j = -;
while (i < wLen){
if (j == - || word[i] == word[j]) fail[++i] = ++j;
else j = fail[j];
}
}

四、动手


匹配的时候,有问题,找fail,看题目,改条件。

 void setFail(){
int i = , j = -;
while (i < wLen){
if (j == - || word[i] == word[j]) fail[++i] = ++j;
else j = fail[j];
}
}
int fid(){
int i = , j = ;
while (i < tLen){
if (j == - || a[i] == word[j]) ++i, ++j;
else j = fail[j];
if (j == wLen){/*该做啥就做啥*/}
}
return -;
}

开始匹配

然后来一波入门题

POJ 3461/HDU 1686,HDU 2203,HDU 2594,HDU 1711


本渣才学疏浅,璞玉难琢,望各位神犇不吝赐(da)教(lian)。

【面向打野编程】——KMP算法入门的更多相关文章

  1. 「面向打野编程」iOS多线程:CGD

    「面向打野编程」iOS多线程:CGD 前言 参考网络其他文章而写,渣水平,抛砖引玉. 虽然Concurrent意思为并发,但由于队列的实际效果,以下称为并行队列. 当前iPhone的CPU核心数远小于 ...

  2. 【初识】KMP算法入门(转)

    感觉写的很好,尤其是底下的公式,易懂,链接:http://www.cnblogs.com/mypride/p/4950245.html 举个例子 模式串S:a s d a s d a s d f a  ...

  3. 【初识】KMP算法入门

    举个例子 模式串S:a s d a s d a s d f a s d 匹配串T:a s d a s d f 如果使用朴素匹配算法—— 1 2 3 4 5 6  8 9 a s d a s d a s ...

  4. KMP算法入门讲解

    字符串匹配问题.假设文本是一个长度为$n$的字符串$T$,模板是一个长度为$m$的字符串$P$,且$m\leq n$.需要求出模板在文本中的所有匹配点$i$,即满足$T[i]=P[0],T[I+1]= ...

  5. KMP算法入门

    学一把看毛片算法我觉得自己才能变得更加出色 明明昨天的题我都知道怎么模拟了,但是还是不会改KMP,是我学丑了 KMP是Knuth-Morris-Pratt三人设计的线性时间字符串匹配算法 nxt数组的 ...

  6. 【React】学习笔记(一)——React入门、面向组件编程、函数柯里化

    课程原视频:https://www.bilibili.com/video/BV1wy4y1D7JT?p=2&spm_id_from=pageDriver 目录 一.React 概述 1.1.R ...

  7. C#面向服务编程技术WCF从入门到实战演练

    一.WCF课程介绍 1.1.Web Service会被WCF取代吗? 对于这个问题阿笨的回答是:两者在功能特性上却是有新旧之分,但是对于特定的系统,适合自己的就是最好的.不能哪一个技术框架和行业标准作 ...

  8. 第五章 面向方面编程___AOP入门

    上一篇讲了 AOP 和 OOP 的区别,这一次我们开始入门 AOP .实现面向方面编程的技术,主要分为两大类: 一是 采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行: ...

  9. 大型 web 前端架构设计-面向抽象编程入门

    https://mp.weixin.qq.com/s/GG6AtBz6KgNwplpaNXfggQ 大型 web 前端架构设计-面向抽象编程入门 曾探 腾讯技术工程 2021-01-04   依赖反转 ...

随机推荐

  1. 这个Glance的界面该怎么看出问题,为什么状态是SOCKT?

    这个glance的状态图有问题吗?

  2. POJ 3267:The Cow Lexicon(DP)

    http://poj.org/problem?id=3267 The Cow Lexicon Time Limit: 2000MS   Memory Limit: 65536K Total Submi ...

  3. 什么情况下用+运算符进行字符串连接比调用StringBuffer/StringBuilder对象的append性能好

    如果在编写代码的过程中大量使用+进行字符串评价还是会对性能造成比较大的影响,但是使用的个数在1000以下还是可以接受的,大于10000的话,执行时间将可能超过1s,会对性能产生较大影响.如果有大量需要 ...

  4. AngularJS 用 Interceptors 来统一处理 HTTP 请求和响应

    Web 开发中,除了数据操作之外,最频繁的就是发起和处理各种 HTTP 请求了,加上 HTTP 请求又是异步的,如果在每个请求中来单独捕获各种常规错误,处理各类自定义错误,那将会有大量的功能类似的代码 ...

  5. python:配置文件configparser

    #-*- coding:utf8 -*- # Auth:fulimei import configparser #第一个标签 conf=configparser.ConfigParser() conf ...

  6. C++TSL之map容器(悲伤的故事)

    说一个悲伤地故事! 这几天正在加紧时间学STL!昨天刚刚勉强把map弄懂一点点.(故事的前提) 今天,来到平台准备刷有关map的题,老师推荐了一道题目.说是有关map.然后..不会!! 后来,百度.. ...

  7. ZOJ 3860: - Find the Spy

    3860 - Find the Spy Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu S ...

  8. easyui tab 关闭

    <div id="mm" class="easyui-menu" style="width:150px;">        &l ...

  9. Sqlite查询时间段内的数据问题解决!

    最近搞Sqlite本地查询,需求为查询某时间段内的数据,在SQL中我们都知道为: select * from tblName where rDate Between '2008-6-10' and   ...

  10. Python学习笔记-Day1-Python基础

    1.python诞生 关于Python的起源,吉多·范罗苏姆在1996年写到: 六 年前,在1989年12月,我在寻找一门“课余”编程项目来打发圣诞节前后的时间.我的办公室会关门,但我有一台家用电脑, ...