感觉写的很好,尤其是底下的公式,易懂,链接:http://www.cnblogs.com/mypride/p/4950245.html

举个例子

模式串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 7 8 9

a s d a s d a s d f a s d

a s d a s d f

1 2 3 4 5 6

此时,匹配到了S7和T7了,S7为a而T7为f,不匹配那么朴素的匹配算法会这么做——

1 2 3 4 5 6 7 8 9

a s d a s d a s d f a s d

a s d a s d f

1 2 3 4 5 6 7

这时,我们会发现,模式串回溯到了S2,而匹配串回溯到了T1。

很明显,这会极大的降低算法的效率,在最坏情况下,我们需要将模式串几乎每个元素都查询一次,而每次查询都从匹配串的串首走到接近串尾,这样的时间复杂度为n*m,其中n和m分别为模式串和匹配串的长度。

那么我们是否有可能降低时间复杂度呢?答案是肯定的——很明显我们只需要想办法减少回溯,就可以达到效果。Kmp算法就是使用这种方法节省时间的。

1 2 3 4 5 6 7 8 9

a s d a s d a s d f a s d

a s d a s d f

1 2 3 4 5 6 7

这个东西很熟悉吧?刚刚出现过一次。

那么,kmp算法会怎么执行下一步呢?答案如下——

1 2 3 4 5 6 7 8 9

a s d a s d a s d f a s d

a s d a s d f

1 2 3 4 5 6 7

注意这一步!这里的模式串根本没有回溯,只是将匹配串向后移动了若干步。这样,最坏情况只是将模式串走一遍,然后将匹配串走一遍,当然了,匹配串里 面的部分元素会走多次,但是,很明显这种算法会将n*m降低到n+k,这个k和m内部部分元素的重复次数有关,最大不会超过n(当然这是我自己证明得到 的,不一定正确,以后我还会继续证明的)。

好了,方法知道了,那么怎么实现呢?

换句话说,怎么实现迅速的移动匹配串呢?答案是——添加一个Next数组,标记匹配串中的特性。

这个Next数组的特性很明显

  1. Next[0] = -1,即这是第一个元素,前面没有可以替换它的。
  2. Next[j] = k ; { k | T[0] = T[j-k], T[1] = T[j-k+1],... , T[k-1] = T[j-1]}。
  3. Next[j] = 0; 其他情况。

举例:

匹配串T: a  s  d  a  s  d  f

Next:   -1  0  0  0  1  2  3

具体见代码——

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;

;

char s[N], t[N];
int Next[N];
int lenS, lenT;

void kmpNext(char* T)                                           //计算Next数组
{
    ;
    Next[] = -;                                               //Next[0] = -1
    while(i < lenT)
    {
        ;
        while(T[j] == T[i])                                     //Next[i] = j; { j | T[0] = T[i-j], T[1] = T[i-j+1],... , T[j-1] = T[i-1]}
        {
            Next[i] = j;
            i++;
            j++;
        }
        Next[i] = j;                                            //同上,或等于0
        i++;
    }
}

bool kmp(char* S, char* T)                                      //kmp
{
    lenS = strlen(S);
    lenT = strlen(T);
    kmpNext(T);
    , j = ;
    while(i < lenS && j < lenT)                                 //当模式串或匹配串走完时退出
    {
        )
        {
            i++;
            j = ;
        }
        else if(S[i] == T[j])
        {
            i++;
            j++;
        }
        else j = Next[j];
    }
    ;                                     //如果匹配串走完,表示匹配串是模式串的子串
    ;
}

int main()
{
    //freopen("test.in", "r", stdin);
    while(~scanf("%s%s", s, t))
    {
        if(kmp(s, t)) printf("Yes\n");
        else printf("No\n");
    }
    ;
}

【初识】KMP算法入门(转)的更多相关文章

  1. 【初识】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 ...

  2. 【面向打野编程】——KMP算法入门

    一.问题 咱们先不管什么KMP,来看看怎么匹配两个字符串. 问题:给定两个字符串,求第二个字符串是否包含于第一个字符串中. 为了具体化,我们以 ABCAXABCABCABX 与 ABCABCABX为例 ...

  3. KMP算法入门讲解

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

  4. HDU_1711_初识KMP算法

    Number Sequence Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  5. KMP算法入门

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

  6. KMP算法——从入门到懵逼到了解

    本博文參考http://blog.csdn.net/v_july_v/article/details/7041827 关于其它字符串匹配算法见http://blog.csdn.net/WINCOL/a ...

  7. KMP算法之从懵逼到入门

    写本文的目的: 1.加深自己的理解,以便自己日后复习 2.给看到此文的人一点启发 KMP算法看懂了就觉得特别简单,思路也好理解,但是看不懂之前,查各种资料看大佬的博客,都很懵逼...... 1.  算 ...

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

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

  9. KMP算法的Next数组详解

    转载请注明来源,并包含相关链接. 网上有很多讲解KMP算法的博客,我就不浪费时间再写一份了.直接推荐一个当初我入门时看的博客吧:http://www.cnblogs.com/yjiyjige/p/32 ...

随机推荐

  1. 由<a>标签的onclick影出来的问题

    今天做了一个 通过 document.getElementByName()的方法获得一个标签a的集合.tag_a=window.docu..... 接着需要给每个标签都加一个onclick事件. fo ...

  2. 【转】完美解除Windows7的驱动程序强制签名限制

    原文网址:http://nick.txtcc.com/index.php/nocategory/290 Windows 7很J,很多驱动程序都无法安装,因为Windows 7不像Vista,必须要求所 ...

  3. ChannelOption.TCP_NODELAY, true->浅谈tcp_nodelay的作用

    在TCP/IP协议中,无论发送多少数据,总是要在数据前面加上协议头,同时,对方接收到数据,也需要发送ACK表示确认.为了尽可能的利用网络带宽,TCP总是希望尽可能的发送足够大的数据.这里就涉及到一个名 ...

  4. JNI学习2:android 调用C语言方法与C语言调用android方法

    #include <jni.h> #include <stdio.h> #include <stdlib.h> #include <jni.h> #in ...

  5. Andorid面试问题整理

    Acitivty的四中启动模式与特点. standard:默认的启动模式 singleTop:适合那种接受通知启动的页面,比如新闻客户端之类的,可能会给你推送好几次 ,但是每次都是打开同一张页面调用o ...

  6. 利用KMeans聚类进行航空公司客户价值分析

    准确的客户分类的结果是企业优化营销资源的重要依据,本文利用了航空公司的部分数据,利用Kmeans聚类方法,对航空公司的客户进行了分类,来识别出不同的客户群体,从来发现有用的客户,从而对不同价值的客户类 ...

  7. noip2014普及组 比例简化

    题目描述 在社交媒体上,经常会看到针对某一个观点同意与否的民意调查以及结果.例如,对某一观点表示支持的有1498 人,反对的有 902人,那么赞同与反对的比例可以简单的记为1498:902. 不过,如 ...

  8. 【转】DNS劫持和DNS污染的区别

    什么是DNS服务器? 简单来说,DNS服务器就是域名管理系统. DNS(Domain Name System)是域名解析服务器的意思. DNS服务器是干什么的? DNS服务器在互联网的作用是:把域名转 ...

  9. JQuery Pagenation 知识点整理——(function($){...})应用(20150517)

    首先:(function($){...})为Jquery提供的匿名函数: 代码实例(一) <script type="text/javascript"> (functi ...

  10. 简单了解ddos攻击

    1.一种为流量攻击,主要是针对网络带宽的攻击,即大量攻击包导致网络带宽被阻塞,合法网络包被虚假的攻击包淹没而无法到达主机: 2.另一种为资源耗尽攻击,主要是针对服务器主机的攻击,即通过大量攻击包导致主 ...