对于KMP算法来言,我自己感觉文字介绍,方法理解起来相对于代码算是简单的,

KMP算法介绍

1)KMP是一个解决模式串在文本串是否出现过,如果出现过,最早出现的位置的经典算法
2)Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP算法”,常用于在一个文本串S内查找一个模式串P 的出现位置,这个算法由Donald Knuth、Vaughan Pratt、James H. Morris三人于1977年联合发表,故取这3人的姓氏命名此算法.
3)KMP方法算法就利用之前判断过信息,通过一个next数组,保存模式串中前后最长公共子序列的长度,每次回溯时,通过next数组找到,前面匹配过的位置,省去了大量的计算时间
参考资料:https://www.cnblogs.com/ZuoAndFutureGirl/p/9028287.html

举例来说,有一个字符串 Str1 = “BBC ABCDAB ABCDABCDABDE”,判断,里面是否包含另一个字符串 Str2 = “ABCDABD”?
1.首先,用Str1的第一个字符和Str2的第一个字符去比较,不符合,关键词向后移动一位


2.重复第一步,还是不符合,再后移

3.一直重复,直到Str1有一个字符与Str2的第一个字符符合为止

4.接着比较字符串和搜索词的下一个字符,还是符合。

5.遇到Str1有一个字符与Str2对应的字符不符合。


6.这时候,想到的是继续遍历Str1的下一个字符,重复第1步。(其实是很不明智的,因为此时BCD已经比较过了,没有必要再做重复的工作,一个基本事实是,当空格与D不匹配时,你其实知道前面六个字符是”ABCDAB”。KMP 算法的想法是,设法利用这个已知信息,不要把”搜索位置”移回已经比较过的位置,继续把它向后移,这样就提高了效率。)


7.怎么做到把刚刚重复的步骤省略掉?可以对Str2计算出一张《部分匹配表》,这张表的产生在后面介绍

8.已知空格与D不匹配时,前面六个字符”ABCDAB”是匹配的。查表可知,最后一个匹配字符B对应的”部分匹配值”为2,因此按照下面的公式算出向后移动的位数:
移动位数 = 已匹配的字符数 - 对应的部分匹配值
因为 6 - 2 等于4,所以将搜索词向后移动 4 位。

9.因为空格与C不匹配,搜索词还要继续往后移。这时,已匹配的字符数为2(”AB”),对应的”部分匹配值”为0。所以,移动位数 = 2 - 0,结果为 2,于是将搜索词向后移 2 位。

10.因为空格与A不匹配,继续后移一位。

11.逐位比较,直到发现C与D不匹配。于是,移动位数 = 6 - 2,继续将搜索词向后移动 4 位。


12.逐位比较,直到搜索词的最后一位,发现完全匹配,于是搜索完成。如果还要继续搜索(即找出全部匹配),移动位数 = 7 - 0,再将搜索词向后移动 7 位,这里就不再重复了。


13.介绍《部分匹配表》怎么产生的
先介绍前缀,后缀是什么


“部分匹配值”就是”前缀”和”后缀”的最长的共有元素的长度。以”ABCDABD”为例,
-”A”的前缀和后缀都为空集,共有元素的长度为0;
-”AB”的前缀为[A],后缀为[B],共有元素的长度为0;
-”ABC”的前缀为[A, AB],后缀为[BC, C],共有元素的长度0;
-”ABCD”的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;
-”ABCDA”的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为”A”,长度为1;
-”ABCDAB”的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为”AB”,长度为2;
-”ABCDABD”的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0。
这个我们取AB为例,我们在后缀中和2个字符以上的比较,最后发现BD不行,所以有结果共有元素长度为0

14.”部分匹配”的实质是,有时候,字符串头部和尾部会有重复。比如,”ABCDAB”之中有两个”AB”,那么它的”部分匹配值”就是2(”AB”的长度)。搜索词移动的时候,第一个”AB”向后移动 4 位(字符串长度-部分匹配值),就可以来到第二个”AB”的位置。

代码实现:

public class KMPAlgorithm {public static void main(String[] args) {// TODO Auto-generated method stubString str1 = "BBC ABCDAB ABCDABCDABDE";String str2 = "ABCDABD";//String str2 = "BBC";int[] next = kmpNext("ABCDABD"); System.out.println("next=" + Arrays.toString(next));int index = kmpSearch(str1, str2, next);System.out.println("index=" + index); }//写出我们的kmp搜索算法/*** * @param str1 源字符串* @param str2 子串* @param next 部分匹配表, 是子串对应的部分匹配表* @return 如果是-1就是没有匹配到,否则返回第一个匹配的位置*/public static int kmpSearch(String str1, String str2, int[] next) {//遍历 for(int i = 0, j = 0; i < str1.length(); i++) {//需要处理 str1.charAt(i) != str2.charAt(j), 去调整j的大小//KMP算法核心点, 可以验证...while( j > 0 && str1.charAt(i) != str2.charAt(j)) {j = next[j-1]; }if(str1.charAt(i) == str2.charAt(j)) {j++;}            if(j == str2.length()) {//找到了 // j = 3 i return i - j + 1;}}return  -1;}//获取到一个字符串(子串) 的部分匹配值表public static  int[] kmpNext(String dest) {//创建一个next 数组保存部分匹配值int[] next = new int[dest.length()];next[0] = 0; //如果字符串是长度为1 部分匹配值就是0for(int i = 1, j = 0; i < dest.length(); i++) {//当dest.charAt(i) != dest.charAt(j) ,我们需要从next[j-1]获取新的j//直到我们发现 有  dest.charAt(i) == dest.charAt(j)成立才退出//这时kmp算法的核心点while(j > 0 && dest.charAt(i) != dest.charAt(j)) {j = next[j-1];}//当dest.charAt(i) == dest.charAt(j) 满足时,部分匹配值就是+1if(dest.charAt(i) == dest.charAt(j)) {j++;}next[i] = j;}return next;}
}

我们很容易发现kmp的核心就是

 while( j > 0 && str1.charAt(i) != str2.charAt(j)) {j = next[j-1]; }while(j > 0 && dest.charAt(i) != dest.charAt(j)) {j = next[j-1];}

暴力匹配法:

public class ViolenceMatch {public static void main(String[] args) {// TODO Auto-generated method stub//测试暴力匹配算法String str1 = "BBC ABCDAB ABCDABCDABDE";String str2 = "ABCDABD";int index = violenceMatch(str1, str2);System.out.println("index=" + index);}// 暴力匹配算法实现public static int violenceMatch(String str1, String str2) {int i = 0; // i索引指向s1int j = 0; // j索引指向s2while (i < str1.length() && j < str2.length()) {// 保证匹配时,不越界if(str1.charAt(i) == str2.charAt(j)) {//匹配oki++;j++;} else { //没有匹配成功//如果失配(即str1[i]! = str2[j]),令i = i - (j - 1),j = 0。i = i - (j - 1);j = 0;}}//判断是否匹配成功if(j == str2.length()) {return i - j;} else {return -1;}}}

KMP算法(字符串匹配)相关推荐

  1. C++KMP算法字符串匹配(附完整源码)

    C++KMP算法字符串匹配 C++KMP算法字符串匹配完整源码(定义,实现,main函数测试) C++KMP算法字符串匹配完整源码(定义,实现,main函数测试) #include <iostr ...

  2. kmp算法字符串匹配C语言实现

    kmp算法字符串匹配 在leetcode做题时,有道题就是写一个strstr函数,先用思路最简单的直接两个循环做,提示时间超过限制.就查了查kmp的资料 翻了下算法导论,感觉像在看数学书,看不太懂,最 ...

  3. KMP算法-字符串匹配(浅显易懂)

    KMP的经典思想就是:当出现字符串不匹配时,可以记录一部分之前已经匹配的文本内容,利用这些信息避免从头再去做匹配. 本篇将以如下顺序来讲解KMP, 什么是KMP KMP有什么用 什么是前缀表 为什么一 ...

  4. KMP算法字符串匹配

    对于暴力搜索法,当搜索词对应的字符与字符串中的字符不匹配时.将搜索词整个后移一位,再从头逐个比较.这样做虽然可行,但是效率很差,因为你要把"搜索位置"移到已经比较过的位置,重比一遍 ...

  5. KMP算法---字符串匹配

    算法细节详见点击打开链接和点击打开链接 #include <stdio.h> #include <stdlib.h> #define N 7 #define M 15 void ...

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

    百度的一个图文介绍http://www.sohu.com/a/336648975_453160 package Algorithm.kmp;import java.util.Arrays;public ...

  7. [JAVA][算法] [字符串匹配]KMP

    我们为什么需要KMP? 在字符串匹配问题中,我们需要找到匹配串pattern在原串text中的位置,一种显而易见的思路就是暴力匹配,如图所示,我们把pattern放置到text中的每个位置进行比较即可 ...

  8. 字符串算法之KMP(字符串匹配)

    一.背景   给定一个主串(以 S 代替)和模式串(以 P 代替),要求找出 P 在 S 中出现的位置,此即串的模式匹配问题.   Knuth-Morris-Pratt 算法(简称 KMP)是解决这一 ...

  9. 数据结构与算法 / 字符串匹配 / BF、PK 算法

    零.前言 为了下面便于说明,先定义两个名词,分别是主串和模式串.在字符串 A 中查找字符串 B,则 A 为主串,B 为模式串. 假设,主串中字符数量为 L1,模式串的字符数量为 L2 . 一.BF 算 ...

  10. 头歌-数据结构与算法-字符串匹配

    第1关:实现朴素的字符串匹配 #include <stdio.h> #include <stdlib.h> #include "mystr.h" #prag ...

最新文章

  1. 关于微软Silverlight,你应该知道的10件事
  2. 在线学html5,HTML5 在线学习自我演进的导弹系统
  3. VS下对Resx资源文件的操作
  4. python数据分析张俊红_关于数据分析我们来聊聊Python
  5. python最简单单例模式_Python单例模式的4种实现方法 | 学步园
  6. Python3--爬取数据之911网站信息爬取
  7. tf.control_dependencies()控制计算流图
  8. python输入生日判断星座_用java编一个程序能通过用户输入的生日判断用户的星座。请大神们给点提示或者思路吧。规定不能自定义方法...
  9. php 位运算 负数,php的位运算详解
  10. js遍历对象的几种方法
  11. 前端调试你还在console.log吗,那你就out, debugger那么好用,你都不用呀
  12. 【记】接口自动化测试,完整入门篇
  13. hihocoder#1513 : 小Hi的烦恼
  14. 计算机组成原理—存储系统总结
  15. pg 定时删除_定时删除网站文件
  16. MathType7数学公式编辑使用计算详细教程
  17. Android连接MySQL数据库
  18. MSSQL · 实现分析 · SQL Server实现审计日志的方案探索
  19. IDempiere介绍
  20. HCNA基础篇问答式笔记整理

热门文章

  1. 惩戒翻倍对抗利率下行,宜信、达飞、恒昌与逃废债互撕
  2. 企业微信如何创建微盘共享空间?
  3. 老虎证券国际完成5亿C轮融资 估值10.6亿美元成新独角兽
  4. 塞外风光,雁门雄关,古韵大同”塞北研学旅行团
  5. 01-旭日X3派测评——开箱测试系统烧写性能初测
  6. 对电瓶车管控问题的思考
  7. RT-Thread—STM32—enc28j60
  8. mediasoup 学习笔记 【二】Router 房间
  9. 安装ACDSee 7指南
  10. google 天气预报API