一、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. ssh跳转设置

    SSH工具的非常规使用 原创 景朝阳 FreeSWITCH中文社区 今天   说明:本文所有的命令是基于OpenSSH客户端7.4p1版本.如果出现命令不正确,请检测是否为此OpenSSH版本. 设置 ...

  2. systemctl --now参数

    1.我们安装一个httpd服务来测试一下 --now参数 yum install httpd 2.查看一下当前服务状态  可以看到服务没有启动 而且服务没有自启 [root@master1 ~]# s ...

  3. Selenium系列5-XPath路径表达式

    Xpath介绍 XPath 使用路径表达式在 XML 文档中进行导航 XPath 使用路径表达式来选取 XML 文档中的节点或者节点集.这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似. ...

  4. HDU1166敌兵布阵(线段树单点更新)

    线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点.       对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b ...

  5. 自制C++游戏 迷宫

    1 #include<bits/stdc++.h> 2 #include<conio.h> 3 using namespace std; 4 char mg[17][17]={ ...

  6. 解析Markdown文件生成React组件文档

    前言 最近做的项目使用了微前端框架single-spa. 对于这类微前端框架而言,通常有个utility应用,也就是公共应用,里面是各个子应用之间可以共用的一些公共组件或者方法. 对于一个团队而言,项 ...

  7. Java基础系列(18)- if选择结构

    if单选择结构 我们很多时候需要去判断一个东西是否可行,然后我们才去执行,这样一个过程在程序中用if语句来表示 语法 if (布尔表达式){ //如果布尔表达式为True将执行的语句 } packag ...

  8. 华为云计算IE面试笔记-FusionSphere Openstack有哪些关键组件,各组件主要功能是什么?三种存储接入组件的差异有哪些?

    1. Nova:在OpenStack环境中提供计算服务,负责计算实例(VM,云主机)生命周期的管理,包括生成.调度和回收.Nova不负责计算实例的告警上报(FC管). 2. Cinder:为计算实例提 ...

  9. 联表多字段update更新语句

    前言 最近需要写联表多字段update更新语句,发现不同的数据库,SQL语法也不一样,正好我这里有MySQL.Oracle.PgSQL三种数据库环境,分别练习.实操这三种数据库的联表update语句 ...

  10. UVa/数组与字符串习题集

    UVa-272. Description: TEX is a typesetting language developed by Donald Knuth. It takes source text ...