一、问题


  咱们先不管什么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. UI优化

    进入正题,我们这一篇文章会提到为什么使用HierarchyViewer,怎么使用HierarchyViewer,后者内容会多一下. 为什么使用HierarchyViewer 不合理的布局会使我们的应用 ...

  2. DButil

    纲要: Properties prop = new Properties(); BasicDataSource ds = new BasicDataSorce(); Connection conn = ...

  3. linux C判断文件是否存在【转】

    转自:http://blog.csdn.net/kingjo002/article/details/8442146 一.access函数 功能描述: 检查调用进程是否可以对指定的文件执行某种操作. 用 ...

  4. php中urlencode与rawurlencode的区别有那些呢

    urlencode 函数: 返回字符串,此字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,空格则编码为加号(+).此编码与 WWW 表单 POST 数据的编码 ...

  5. ecshop后台增加模块菜单详细教程(图)

    我们有时候针对ecshop如此开发,想在后台加一些菜单,最模板以前提供过教程,但是并非很系统,今天最模板抛砖引玉图文教程告诉大家:如何在ecshop后台增加模块菜单! 首先需要修改四个文件:inc_p ...

  6. git 冲突

    git中冲突会用特殊的标记 (<<<<<<<=======>>>>>>>) 特殊标记<<<< ...

  7. 错误描述: 抱歉,该商品的交易金额与原先的不一致,请重新创建交易付款。 错误代码: TRADE_TOTALFEE_NOT_MATCH

    由于在支付宝最后支付,出现了问题导致未能支付成功,而支付宝已经记录了当前的网站订单号(out_trade_no),所以下次再以同一张订单进行支付时,就必须与之前的金额一致,否则就报上面的错. 解决方法 ...

  8. csharp通过dll调用opencv函数,图片作为参数

    [blog 项目实战派]csharp通过dll调用opencv函数,图片作为参数          ​一直想做着方面的研究,但是因为这个方面的知识过于小众,也是由于自己找资料的能力比较弱,知道今天才找 ...

  9. JAVA基础知识之JVM-——使用反射生成并操作对象

    Class对象可以获取类里的方法,由Method对象表示,调用Method的invoke可以执行对应的方法:可以获取构造器,由Constructor对象表示,调用Constructor对象的newIn ...

  10. ural 1110,快速幂

    题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1110 题意:   X^N % M = Y,X=[0,M-1];没有输出-1: #incl ...