KMP算法利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。

Next()函数的详解

  • 把将要进行next计算的字符串S分成 k ,j 前后两串,k代表前串开头所在的序号,j代表后串开头所在的序号,起始的时候j=1,k=0。
  • 我们比较一下前串 后串是否相等,要怎么比较呢,肯定是比较S[j]==S[k],如果相等,那么next[j+1]=k+1,然后j++,k++。关键就是理解这个next[j+1]=k+1(为什么k+1?):简单说就是S串中的第j+1个字符的next函数值由他前面的字符与前串相等的个数来决定,就是说串中的第j+1个字符的next函数值,是由他前面的字符串决定的。
  • 当S[j]!=S[k],即不相等的时侯,那么j不动,k返回到开头(因该是next[k]位置,便于理解先假设是返回k=0处),即从头比较S[0]与S[j],S[1]与S[j+1]。

  例如:第 j+1 个字符的next函数值next[j+1]等于3,意味着它的前三个字符串,S[j-2]S[j-1]S[j] =S[0]S[1]S[2]。

例一:模式串:abcaabcba

下标

0

1

2

3

4

5

6

7

8

模式串

a

b

c

a

a

b

c

b

a

next值

-1

0

0

0

1

1

2

3

0

1.第一个字符的next值令为-1。令第二个字符b的next值为0。初始k=0,j=1。开始比较S[k] 和S[j]。

2.比较S[0] !=S[1],所以j++,k不变,next[j=2]=k=0。

3.比较S[0] !=S[2],所以j++,k不变,next[j=3]=k=0。

4.比较S[0]==S[3],所以j++,k++,next[j=4]=k=1。

5.k=1了,所以比较S[1] !=S[4],k返回到next[k]位置,即k=next[1]=0,然后比较S[k=0] == S[4],所以 j++,k++,next[j=5]=k=1。

6.比较S[1]==S[5],所以j++,k++,next[6]=k=2。

7.比较S[2]==S[6],所以j++,k++,next[7]=k=3。

8.比较S[3] !=S[7],所以k返回到next[k=3]位置,即k=next[3]=0,然后比较S[k=0] !=S[7],所以j++,k=0不变,next[8]=k=0。

在例一中,每次不相等时返回的都是k=next[k]=0,都是返回到了开头,下面一个不是返回到开头0的情况:

例二:模式串:aabcaaabaac

下标

0

1

2

3

4

5

6

7

8

9

10

模式串

a

a

b

c

a

a

a

b

a

a

c

next值

-1

0

1

0

0

1

2

2

3

1

2

从 j=5,k=1的时候开始

5.比较S[1]==S[5],所以j++,k++,next[j=6]=k=2。

6.比较S[2] !=S[6],所以k返回到next[k=2]位置,即k=next[2]=1,然后比较S[k=1]==S[6],所以 j++,k++,next[7]=k=2。

……

因此,发现K的退回是退回到next[k]的位置,即S[j]!=S[k]时,k=next[k]。

KMP的算法思想

和BF算法相比,KMP算法主要是在模式串上下功夫,通过先求得模式串对应的next[ ]数组,当两个字符串中字符匹配失败时候将模式串的下标回溯到next[ ]中存储的下标位置,而BF算法是直接回溯到模式串的0下标,即开始第一个字符。所以KMP算法的时间复杂度要比BF算法好。

KMP算法代码

 #include<stdio.h>
#include<string.h> char* s = "aabcaaabaac";
char* t = "aac"; int next[]; //定义next数组 void getNext(char *s, int next[])
{
int k=-; / /k代表前串起始位置
int j=; //后串起始位置,一直增加
next[] = -; //令第一个字符的next值为-1 while(j < strlen(s) - ) //当后串小于最大下标-1
{
if(k == - || s[j] == s[k]) //匹配的情况下,即s[j]==s[k],next[j+1]=k+1;
{
++j;
++k;
next[j] = k;
}
else //若不匹配,即p[j]!=p[k],k=next[k]
k = next[k];
}
} int KMP(char* s, char* t)
{
int i = ; //i从s串开始
int j = ; //j从t串开始
int sLength = strlen(s); //s串的长度
int tLength = strlen(t); //t串的长度
while((i < sLength) && (j < tLength)) //当下标i和j都不越界时
{
if(j == - || s[i] == t[j]) //当模式串t中第一个字符与目标串s中某个字符匹配失败时,i应该移动到目标串s的下一个目标,再和模式串t的第一个字符进行比较,或者s的第i个字符和t的第j个字符相等,则将i++和j++
{
i++;
j++;
}
else
{
//i=i-j+1;j=0; //这是普通的BF算法,将模式串的下标从0开始
j = next[j]; //KMP算法是将模式串的j下标从next[j]开始
}
}
if(j >= tLength)
return i - tLength;
else
return ;
} int main()
{
getNext(s, next);
printf("%d", + KMP(s, t));
return ;
}

KMP字符串匹配算法详解的更多相关文章

  1. KMP字符串模式匹配详解(zz)

    刚看到位兄弟也贴了份KMP算法说明,但本人觉得说的不是很详细,当初我在看这个算法的时候也看的头晕昏昏的,我贴的这份也是网上找的.且听详细分解: KMP字符串模式匹配详解 来自CSDN     A_B_ ...

  2. KMP字符串模式匹配详解

    KMP字符串模式匹配详解 http://www.cppblog.com/oosky/archive/2006/07/06/9486.html

  3. KMP字符串模式匹配详解(转)

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

  4. KMP字符串匹配算法翔解❤

    看了Angel_Kitty学姐的博客,我豁然开朗,写下此文: 那么首先我们知道,kmp算法是一种字符串匹配算法,那么我们来看一个例子. 比方说,现在我有两段像这样子的字符串: 分别是T和P,很明显,P ...

  5. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  6. jquery $.trim()去除字符串空格详解

    jquery $.trim()去除字符串空格详解 语法 jQuery.trim()函数用于去除字符串两端的空白字符. 作用 该函数可以去除字符串开始和末尾两端的空白字符(直到遇到第一个非空白字符串为止 ...

  7. Python 字符串方法详解

    Python 字符串方法详解 本文最初发表于赖勇浩(恋花蝶)的博客(http://blog.csdn.net/lanphaday),如蒙转载,敬请保留全文完整,切勿去除本声明和作者信息.        ...

  8. shell字符串操作详解

    shell字符串操作详解的相关资料. 1.shell变量声明的判断  表达式 含义 ${var} 变量var的值, 与$var相同 ${var-DEFAULT} 如果var没有被声明, 那么就以$DE ...

  9. C#的String.Split 分割字符串用法详解的代码

    代码期间,把代码过程经常用的内容做个珍藏,下边代码是关于C#的String.Split 分割字符串用法详解的代码,应该对码农们有些用途. 1) public string[] Split(params ...

随机推荐

  1. VSCode常用插件之EditorConfig for vs code 使用

    更多VSCode插件使用请访问:VSCode常用插件汇总 当大家在公司工作时,不可能永远是一个人维护一个项目,当多个人参与一个项目,每个人使用的编辑器不一样,代码风格自然也不一样,那么如何让使用不同编 ...

  2. 栈和队列----设计一个有getMin功能的栈

    设计一个有getMin功能的栈 设计一个具有getMin功能的栈,可以返回栈中的最小的元素,可以使用现有的栈的数据结构,要求pop/push/getMin操作的时间复杂度是O(1). package ...

  3. 合唱队形【dp】

    链接:https://ac.nowcoder.com/acm/contest/1082/C来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语言2621 ...

  4. PIE-SDK For C++栅格数据集的读取

    1.功能简介 栅格数据包含很多信息,在数据的运用中需要对数据的信息进行读取,目前PIE SDK支持多种数据格式的数据读取,下面对栅格数据格式的数据读取功能进行介绍. 2.功能实现说明 2.1 实现思路 ...

  5. vue配置开发,测试,生产环境api

    npm run build 调用开发环境接口,打包开发环境npm run build:test 调用测试环境接口,打包测试环境npm run build:prod 调用生产环境接口,打包生产环境 vu ...

  6. C++——指针2-指向数组的指针和指针数组

    7.4 指向数组元素的指针 声明与赋值 例:int a[10], *pa; pa=&a[0]; 或 pa=a[p1] ; 通过指针引用数组元素,经过上述声明及赋值后: *pa就是a[0],*( ...

  7. JFinal获取多个model

    个人博客 地址:http://www.wenhaofan.com/article/20180930112646 由于jfinal框架自身没有实现获取多个同一类型的Model的方法,导致获取ModelL ...

  8. 二分-C - Pie

    C - Pie My birthday is coming up and traditionally I'm serving pie. Not just one pie, no, I have a n ...

  9. xshell连接本地虚拟机中的centos

    1. 一开始Xshell连接不上(设置为DHCP 动态IP)虚拟机上的centos8 参考这篇博文,将centos上的DHCP改为static 静态IP xshell连接本地虚拟机中的centos 2 ...

  10. selenium获取短暂出现元素的xpath路径

    1. pip install beautifulsoup4  :安装beautifulsoup4 2. from bs4 import BeautifulSoup 3. bs = BeautifulS ...