[edit by xingoo]

kmp算法其实就是一种改进的字符串匹配算法。复杂度可以达到O(n+m),n是参考字符串长度,m是匹配字符串长度。

传统的算法,就是匹配字符串与参考字符串挨个比较,如果相同就比较下一个,如果不相同,就返回上一次的结果,再重新比较。

如图1 如果失败则字符串会重新用S(参考字符串)的第二个,与T(匹配字符串)的第一个比较,知道全部符合查找,或找不到为止。

此时发现S[5] != T[5],因此用S[1]与T[0]进行比较。

此时发现S[1]!=T[0],因此用S[2]与T[0]比较。

此时,仍然不相等,继续后移。

此时,S[3] == T[0],继续比较,发现所有T元素都在S中找到,满足查找,返回开始匹配的下标3.

传统代码

 int old_index(char * S,char * T){
int i=;
int j=;
while(i<strlen(S) && j<strlen(T)){
if( S[i] == T[j] ){
++i;
++j;
}
else{
i = i-j+; //上一次的下一个
j=;
}
}
if(j == strlen(T))
return i-strlen(T);
else
return -;
}

这种比较忽略了一个问题,就是在T中,abcabx,第一个字符串因为不跟第二个,第三个一样,因此,在一开始的匹配中,可以直接跳过比较,直接从S的第三个元素开始比较。这里就涉及到一个概念:最短子串对称匹配。

首先,初始化,当j=0时,next(j)=-1;

当j=1时,字符串0到j-1,只有"a",因此 next(j) = 0;

当j=2时,字符串0到j-1,字符串为"ab",因此next(j) = 0;

当j=3时,字符串0到j-1,字符串为"abc",因此next(j) = 0;

当j=4时,字符串0到j-1,字符串为"abca",此时,前缀a在末尾出现,因此next(j) = 1;

当j=5时,字符串0到j-1,字符串为"abcab",此时,前缀ab在末尾出现,因此next(j) = 2;

最后得到next的数组为"-1 0 0 0 1 2"。

按照这个方法:

ababab的next数组为"-1 0 0 1 2 3 4"

这里面,当j=5时,字符串"ababa",前缀是"aba",后缀也是"aba",因此next值为3.

计算next数组详细代码

void getNext(char * T,int *next){
int i,j;
i=;
j=-;
next[]=-;
while(i<strlen(T)){
if(j == - || T[i] == T[j]){
++i;
++j;
next[i] = j;
}
else{
j = next[j];
}
}
}

kmp匹配代码

int kmp(char* S,char * T){
int i=;
int j=;
int next[MAX];
getNext(T,next);
while(i<strlen(S) && j<strlen(T)){
printf("i %d-%c j %d-%c\n",i,S[i],j,T[j]);
if(j== || S[i]==T[j]){
++i;
++j;
}else{
j = next[j];
printf("j back to %d\n",j);
}
}
if(j == strlen(T))
return i-strlen(T);
else
return ;
}

全部代码

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20 void getNext(char * T,int *next);
int kmp(char * S,char * T);
int old_index(char * S,char * T); int main()
{
char * s = "acabbabababc";
char * t = "ababab"; //printf("the pos is:%d\n\n",old_index(s,t));
//printf("the pos is:%d\n\n",old_index(m,t));
//printf("the pos is:%d\n\n",old_index(n,t));
printf("the pos is:%d\n",kmp(s,t));
return ;
} void getNext(char * T,int *next){
int i,j;
i=;
j=-;
next[]=-;
while(i<strlen(T)){
if(j == - || T[i] == T[j]){
++i;
++j;
next[i] = j;
}
else{
j = next[j];
}
}
} int kmp(char* S,char * T){
int i=;
int j=;
int next[MAX];
getNext(T,next);
while(i<strlen(S) && j<strlen(T)){
printf("i %d-%c j %d-%c\n",i,S[i],j,T[j]);
if(j== || S[i]==T[j]){
++i;
++j;
}else{
j = next[j];
printf("j back to %d\n",j);
}
}
if(j == strlen(T))
return i-strlen(T);
else
return ;
}
int old_index(char * S,char * T){
int i=;
int j=;
while(i<strlen(S) && j<strlen(T)){
if( S[i] == T[j] ){
++i;
++j;
}
else{
i = i-j+; //上一次的下一个
j=;
}
}
if(j == strlen(T))
return i-strlen(T);
else
return -;
}

运行结果

KMP算法初探的更多相关文章

  1. 初探KMP算法

            数据结构上老师也没讲这个,平常ACM比赛时我也没怎么理解,只是背会了代码--前天在博客园上看见了一篇介绍KMP的,不经意间就勾起了我的回忆,写下来吧,记得更牢. 一.理论准备      ...

  2. 简单有效的kmp算法

    以前看过kmp算法,当时接触后总感觉好深奥啊,抱着数据结构的数啃了一中午,最终才大致看懂,后来提起kmp也只剩下“奥,它是做模式匹配的”这点干货.最近有空,翻出来算法导论看看,原来就是这么简单(先不说 ...

  3. KMP算法

    KMP算法是字符串模式匹配当中最经典的算法,原来大二学数据结构的有讲,但是当时只是记住了原理,但不知道代码实现,今天终于是完成了KMP的代码实现.原理KMP的原理其实很简单,给定一个字符串和一个模式串 ...

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

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

  5. KMP算法实现

    链接:http://blog.csdn.net/joylnwang/article/details/6778316 KMP算法是一种很经典的字符串匹配算法,链接中的讲解已经是很明确得了,自己按照其讲解 ...

  6. 数据结构与算法JavaScript (五) 串(经典KMP算法)

    KMP算法和BM算法 KMP是前缀匹配和BM后缀匹配的经典算法,看得出来前缀匹配和后缀匹配的区别就仅仅在于比较的顺序不同 前缀匹配是指:模式串和母串的比较从左到右,模式串的移动也是从 左到右 后缀匹配 ...

  7. 扩展KMP算法

    一 问题定义 给定母串S和子串T,定义n为母串S的长度,m为子串T的长度,suffix[i]为第i个字符开始的母串S的后缀子串,extend[i]为suffix[i]与字串T的最长公共前缀长度.求出所 ...

  8. 字符串模式匹配之KMP算法图解与 next 数组原理和实现方案

    之前说到,朴素的匹配,每趟比较,都要回溯主串的指针,费事.则 KMP 就是对朴素匹配的一种改进.正好复习一下. KMP 算法其改进思想在于: 每当一趟匹配过程中出现字符比较不相等时,不需要回溯主串的 ...

  9. 算法:KMP算法

    算法:KMP排序 算法分析 KMP算法是一种快速的模式匹配算法.KMP是三位大师:D.E.Knuth.J.H.Morris和V.R.Pratt同时发现的,所以取首字母组成KMP. 少部分图片来自孤~影 ...

随机推荐

  1. 2015-10-13 晴 tcp/ip卷1

    今年看tcp/ip卷1的内容.苦和甜来自外界,坚强则来自内心,来自一个人的自我努力. 只有勤奋和积极进取的人 才会赢得成功的人生.加油

  2. 安卓 Input Events(输入事件)

    在安卓中,有不止一种方法从你的应用截取用户交互事件.在你的用户界面中考虑事件,途径就是从用户界面中的一个指定的view对象中捕获事件.该view提供了这样做的方法. 在你用来组成你布局的不同的view ...

  3. Linux下信号的简单使用

    1,1个main, 包含2个while, 不要被两个while中的sleep所迷惑,这里只有main()这一个主线程(进程)在运行,程序会按照自上而下顺序执行. 遇到第1个while循环中的sleep ...

  4. 创建Web API

    引言 在公司中用到的都是webAPI的应用程序,这个东西之前没有接触过.但是这个并不是什么新鲜的东西,因我们 之前有mvc的基础,所以说学习这个东西还是比较容易的,在开始的时候自己可能突然蒙圈了.因为 ...

  5. 自动抓取java堆栈

    参数1 进程名字,参数2 最大线程数 例: pid为8888,达到1000个线程时自动抓取堆栈信息 ./autojstack.sh 8888 1000 & #!/bin/bashfileNam ...

  6. PHP 关于回调的用法

    class aClass { public static function directWrite($message) { echo 'this is a static function from a ...

  7. 理解KMP

    KMP字符串模式匹配通俗点说就是一种在一个字符串中定位另一个串的高效算法.简单匹配算法的时间复杂度为O(m*n),KMP匹配算法,可以证明它的时间复杂度为O(m+n).. 一.简单匹配算法 先来看一个 ...

  8. .NET异步编程初识async与await

    这是两个关键字,用于异步编程.我们传统的异步编程方式一般是Thread.ThreadPool.BeginXXX.EndXXX等等.把调用.回调分开来,代码的逻辑是有跳跃的,于是会导致思路不是很清晰的问 ...

  9. 多台服务器最好加上相同的machineKey

      <machineKey validationKey="6E993A81CF4BDCA1C1031528F55DADBB8AF1772A" decryptionKey=&q ...

  10. C#UDP(接收和发送源码)源码完整

    C#UDP(接收和发送源码)源码完整 最近做了一个UDP的服务接收和发送的东西.希望能对初学的朋友一点帮助. 源码如下: 一.逻辑--UdpServer.cs using System;using S ...