一、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. Markdown快捷键详解(源自狂神说Java视频,整理版)

    #加空格 表示是一个标题(一级标题)回车后直接生成 例下 Markdown学习 标题: ##(两个#号)空格加标题名字即为二级标题例下 二级标题 三个#号 加标题名字即为三级标题,与二级标题等有层级关 ...

  2. 尚硅谷Java基础学习笔记

    综述: Java学习图谱: 常见dos命令: 操作案例: Java语言的特点: 面向对象 两个基本概念:类.对象 三个基本特性:封装.继承.多态 健壮性.可继承性 write once,run any ...

  3. 跨域分布式系统单点登录的实现(CAS单点登录)

    1. 概述 上一次我们聊了一下<使用Redis实现分布式会话>,原理就是使用 客户端Cookie + Redis 的方式来验证用户是否登录. 如果分布式系统中,只是对Tomcat做了负载均 ...

  4. ansible 批量安装yum包

    1.首先安装一下ansible yum install ansible 2.修改一下ansible的参数以防ssh过去的时候需要首次判断yes  或者no sed -i 's/#host_key_ch ...

  5. GoLang设计模式07 - 责任链模式

    责任链模式是一种行为型设计模式.在这种模式中,会为请求创建一条由多个Handler组成的链路.每一个进入的请求,都会经过这条链路.这条链路上的Handler可以选择如下操作: 处理请求或跳过处理 决定 ...

  6. sqlite3 import/export db sqlite 导入 导出 数据

    export: $ sqlite3 xxx.db3 > .output xxx.sql >.dump > .q import: $ sqlite3 xxx.db3 > .rea ...

  7. Jemter请求乱码解决方案

    1:jemeter查看结果树乱码 (1)在jmeter的bin目录下找到jmeter.properties这个文件,添加上 sampleresult.default.encoding=utf-8 (2 ...

  8. 鸿蒙内核源码分析(消息队列篇) | 进程间如何异步传递大数据 | 百篇博客分析OpenHarmony源码 | v33.02

    百篇博客系列篇.本篇为: v33.xx 鸿蒙内核源码分析(消息队列篇) | 进程间如何异步传递大数据 | 51.c.h .o 进程通讯相关篇为: v26.xx 鸿蒙内核源码分析(自旋锁篇) | 自旋锁 ...

  9. CF11D-A Simple Task【状压dp】

    正题 题目链接:https://www.luogu.com.cn/problem/CF11D 题目大意 给出\(n\)个点\(m\)条边的一张简单无向图,求它的简单环的个数. \(1\leq n\le ...

  10. P6624-[省选联考2020A卷]作业题【矩阵树定理,欧拉反演】

    正题 题目链接:https://www.luogu.com.cn/problem/P6624 题目大意 \(n\)个点的一张图,每条边有权值,一棵生成树的权值是所有边权和乘上边权的\(gcd\),即 ...