一、KMP算法介绍

  KMP算法与前面的MP算法一脉相承,都是充分利用先前匹配的过程中已经得到的结果来避免频繁回溯。回顾一下MP算法,如下图的模式串偏移,当前模式字符串P的左端的p0与目标字符串T中tj位置对齐。从左向右逐个进行比较,发现 p处的字符a 与 tj+1 处字符b发生失配。同时也表明 P(p0,p1,...,pi-1) 与 T'(tj,tj+1,...,tj+i-1) 是完全匹配的,这一部分子串在图中用字母u标示出。由于发生失配,随即移动模式字符串并进行下一轮的比较。此时,很自然地希望移动之后的结果可以使得模式字符串P中的一个前缀v,可以匹配到子串u的某一部分后缀。所以MP算法引入一个mpNext数组,并用它来对P中最长前缀进行标记。然后根据PmpNext[i] = c 和 Ti+j = b 之间展开下一轮比较。

  在MP算法的基础上再推进一步,继续前面的过程,当模式字符串P完成一次移动后,接下来马上要进行的工作是比较字符 b 和 c,为了避免随之而来的一次失配,在仅仅知道模式字符串P的情况下,保证一次移动后,紧随着前缀字符串v之后的那个字符c不等于原来失配的字符a(满足这个条件的最长前缀v是字符串u的加标边际)。KMP算法需要对mpNext表中符合要求的加标边际进行标识,符合要求指的是:① v可以匹配到u中某个后缀的最长前缀; ② 紧跟在v后面的字符c不同于紧跟在u后面的字符a。

二、kmpNext表的规则

  在mpNext表生成的基础上,建立kmpNext表的规则分为4种情况,其中 1≤j≤m-1:

  1. 如果 mpNext[j] = 0 且 pj = p0,则令kmpNext[j] = -1;

  2. 如果 mpNext[j] = 0 且 pj ≠ p0,则令kmpNext[j] = 0;

  3. 如果 mpNext[j] ≠ 0 且 pj ≠ pmpNext[j],则令kmpNext[j] = mpNext[j];

  4. 如果 mpNext[j] ≠ 0 且 pj = pmpNext[j],则用mpNext[j]中的值替换原来mpNext[j]中的j值,直到情况转换为前面3种情况的一种,从而递归求解kmpNext[j]。

  在 j =0 的位置同样是 -1,并令kmpNext[m] = mpNext[m],m是模式串P的长度。kmpNext[m]的值也是指示了后续进行匹配而需要将模式字符串移动的位数。

  kmpNext表:

j

0

1

2

3

4

5

6

7

p(j)

c

a

a

t

c

a

t

 

mpNext[j]

-1

0

0

0

0

1

2

0

kmpNext[j]

-1

0

0

0

-1

0

2

0

三、代码

 1     public void preKmp(char[] x, int m, int[] kmpNext) {
2 int i, j;
3 i = 0;
4 j = kmpNext[0] = -1;
5 while(i < m-1) {
6 while (j > -1 && x[i] != x[j])
7 j = kmpNext[j];
8 i++;
9 j++;
10 if (x[i] == x[j])
11 kmpNext[i] = kmpNext[j];
12 else
13 kmpNext[i] = j;
14 }
15 }
16
17 public void kmp(String p, String t) {
18 int m = p.length();
19 int n = t.length();
20
21 if (m > n) {
22 System.err.println("Unsuccessful match!");
23 return;
24 }
25
26 char[] x = p.toCharArray();
27 char[] y = t.toCharArray();
28
29 int i = 0;
30 int j = 0;
31 int[] kmpNext = new int[m+1];
32 preKmp(x, m, kmpNext);
33
34 while (j < n) {
35 while (i > -1 && x[i] != y[j])
36 i = kmpNext[i];
37 i++;
38 j++;
39 if (i >= m) {
40 System.out.println("Matching index found at: " + (j - i + 1));
41 i = kmpNext[i];
42 }
43 }
44 }

字符串与模式匹配算法(三):KMP算法的更多相关文章

  1. 字符串匹配算法(三)-KMP算法

    今天我们来聊一下字符串匹配算法里最著名的算法-KMP算法,KMP算法的全称是 Knuth Morris Pratt 算法,是根据三位作者(D.E.Knuth,J.H.Morris 和 V.R.Prat ...

  2. 字符串匹配算法之 kmp算法 (python版)

    字符串匹配算法之 kmp算法 (python版) 1.什么是KMP算法 KMP是三位大牛:D.E.Knuth.J.H.MorriT和V.R.Pratt同时发现的.其中第一位就是<计算机程序设计艺 ...

  3. 字符串的模式匹配算法——KMP模式匹配算法

    朴素的模式匹配算法(C++) 朴素的模式匹配算法,暴力,容易理解 #include<iostream> using namespace std; int main() { string m ...

  4. 模式串匹配之KMP算法

    模式串匹配之KMP算法 KMP算法 模式值计算(next[j]) (1) next[0]=-1,  第一个字符模式值为-1 (2) next[j]=-1, T中下标为j的字符与首字符相同,且j前面的1 ...

  5. 常用算法3 - 字符串查找/模式匹配算法(BF & KMP算法)

    相信我们都有在linux下查找文本内容的经历,比如当我们使用vim查找文本文件中的某个字或者某段话时,Linux很快做出反应并给出相应结果,特别方便快捷! 那么,我们有木有想过linux是如何在浩如烟 ...

  6. 字符串匹配算法之kmp算法

    kmp算法是一种效率非常高的字符串匹配算法,是由Knuth,Morris,Pratt共同提出的模式匹配算法,所以简称KMP算法 算法思想 在一个字符串中查找另一个字符串时,会遇到如下图的情况 我们通常 ...

  7. 动画演示Sunday字符串匹配算法——比KMP算法快七倍!极易理解!

    前言 上一篇我用动画的方式向大家详细说明了KMP算法(没看过的同学可以回去看看). 这次我依旧采用动画的方式向大家介绍另一个你用一次就会爱上的字符串匹配算法:Sunday算法,希望能收获你的点赞关注收 ...

  8. Python 细聊从暴力(BF)字符串匹配算法到 KMP 算法之间的精妙变化

    1. 字符串匹配算法 所谓字符串匹配算法,简单地说就是在一个目标字符串中查找是否存在另一个模式字符串.如在字符串 "ABCDEFG" 中查找是否存在 "EF" ...

  9. 字符串与模式匹配算法(四):BM算法

    一.BM算法介绍 BM算法(Boyer-Moore算法)是罗伯特·波义尔(Robert Boyer)和杰·摩尔(J·Moore)在1977年共同提出的.与KMP算法不同的是,BM算法是模式串P由左向右 ...

随机推荐

  1. jupyter notebook在代码块中多行注释方法

    Ctrl+\是pycharm等IDE内的使用方法,而不是jupyter中的,正确的方法如下: 按住alt后光标变为十字形,沿着行标向下拖,光标变得很长,这时 shift+3 即可注释多行 想要取消注释 ...

  2. 【OI】C++STL初步 排序与检索

    从紫皮书过来的,但是书中内容讲的比较简洁,做一点补充笔记. 一.排序(sort函数) 头文件:<algorithm> 语法:sort(start,end,cmp); start,end必须 ...

  3. 记一次docker compose的低级错误

    记一次docker compose的低级错误 问题 ​ 今天在学习dockercompose的时候,启动docker compose up,结果却出现异常 Error response from da ...

  4. php 的一些问题

    ------------------------------------------------------------------------------ * 绝对路径转化为相对路径 <?ph ...

  5. javascript 对象池

    * 一个对象池的简单应用 tool tip tootip.html <html> <head> <meta charset="UTF-8"> & ...

  6. php 常用算法与函数

    1.一群猴子排成一圈,按1,2,-,n依次编号.然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去-,如此不停的进行下去,直到最后只剩下一只猴子为止,那只猴子就叫 ...

  7. python学习笔记(七)-函数

    函数 方法 功能说白了,函数就是把一堆代码组合到一起,变成一个整体.函数不调用不会被执行.作用在于提高代码的复用性.定义函数 def greet_user(): """关 ...

  8. 基于深度学习的建筑能耗预测01——Anaconda3-4.4.0+Tensorflow1.7+Python3.6+Pycharm安装

    基于深度学习的建筑能耗预测-2021WS-02W 一,安装python及其环境的设置 (写python代码前,在电脑上安装相关必备的软件的过程称为环境搭建) · 完全可以先安装anaconda(会自带 ...

  9. @Value竟然能玩出这么多花样

    前言 对于从事java开发工作的小伙伴来说,spring框架肯定再熟悉不过了.spring给开发者提供了非常丰富的api,满足我们日常的工作需求. 如果想要创建bean实例,可以使用@Controll ...

  10. SpringBoot+WebSocket实时监控异常

    写在前面 此异常非彼异常,标题所说的异常是业务上的异常. 最近做了一个需求,消防的设备巡检,如果巡检发现异常,通过手机端提交,后台的实时监控页面实时获取到该设备的信息及位置,然后安排员工去处理. 因为 ...