KMP算法

应用场景——字符串匹配问题

有一个字符串str1 = “河南河南软件河南大学河南科技大学软件学院”和str2=“河南科技大学”

现在要判断str1是否含有str2,如果存在,就返回第一次出现的位置,如果没有,则返回-1

这是很多字符串匹配问题的例子

我们首先会想到的是暴力匹配

如果用暴力匹配的思路,并假设现在str1匹配到i位置,子串str2匹配到j位置,则有:

1.如果当前字符匹配成功( 即str1[i] == str2[j]),则i++, j++, 继续匹配下一个字符

2.如果失配(即str1[i]!= str2[j]),令i=i-(j-1), j=0。 相当于每次匹配失败时,i回溯,j被置为0

3.用暴力方法解决的话就会有大量的回溯,每次只移动一位,若是不匹配,移动到下一位接着判断,浪费了大量的时间。(不可行!)

package 字符串匹配问题;
public class ViolenceMatch {public static void main(String[] args) {// TODO Auto-generated method stubString str1 = "河南河南软件河南大学河南科技大学软件学院";String str2 = "河南科技大学";int index = violenceMatch(str1, str2);System.out.println(index);}//暴力匹配算法public static int violenceMatch(String str1,String str2){char[] s1 = str1.toCharArray();char[] s2 = str2.toCharArray();int s1Len = s1.length;int s2Len = s2.length;int i = 0;//指向s1int j = 0;//指向s2while(i<s1Len && j<s2Len){//保证匹配不越界if(s1[i] == s2[j]){//匹配成功i++;j++;}else{i = i - (j-1);j = 0;}}//判断是否匹配成功if(j == s2Len){return i - j;}else{return -1;}}
}

KMP算法介绍

KMP是一个解决模式串在文本串是否出现过,如果出现过,最早出现的位置的经典算法

KMP方法算法就利用之前判断过信息,通过一个next数组保存模式串中前后最长公共子序列的长度每次回溯时,通过next数组找到,前面匹配过的位置,省去了大量的计算时间

案例

有一个字符串str1= “BBC ABCDAB ABCDABCDABDE”,和一个子串str2=“ABCDABD”

现在要判断str1是否含有str2,如果存在,就返回第-次出现的位置,如果没有,则返回-1
要求:使用KMP算法完成判断,不能使用简单的暴力匹配算法.

文字叙述过程我就不写了,毕竟很多大佬写的很清楚了,这里有兴趣的可以去搜一下,我贴出来一个老哥的链接https://blog.csdn.net/dark_cy/article/details/88698736

package 字符串匹配问题;
import java.util.Arrays;
public class KMPAlgorithm {public static void main(String[] args) {// TODO Auto-generated method stubString str1 = "BBC ABCDAB ABCDABCDABDE";String str2 = "ABCDABD";int next[] = kmpNext("ABCDABD");  //[0,1]System.out.println("next"+Arrays.toString(next));int index = kmpSearch(str1, str2, next);System.out.println(index);}//获取到一个字符串(子串)的部分匹配值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)成立才推出while(j > 0 && dest.charAt(i) != dest.charAt(j)){j = next[j-1];}//当dest.charAt(i) == dest.charAt(j)if(dest.charAt(i) == dest.charAt(j)){//部分匹配值就需要+1j++;}next[i] = j;}return next;}//写出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)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()){//找到了return i - j + 1;}}return -1;}
}

个人理解

KMP算法的难点就在于这个部分匹配值,关于这点得要自己去理解,有兴趣的可以在网上搜搜,与一般匹配方法相同的是,当字符相等的时候,都是往后移一位,继续去判断,不同于暴力破解那种方法的地方在于,当两个字符不相等的时候,暴力破解是把我们开始匹配的位置放到了刚才起点的后一个位置,然后从这个位置继续匹配一边,会很麻烦,而KMP算法是根据我们的部分匹配值的返回值给我们找好重新匹配的位置,如果你明白了这个匹配值怎么来的,你也就知道为什么要移动到那个位置,总的来说,KMP算法的核心就在于部分匹配值和下面这段代码

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

也就是说当我们的子串匹配到位置的下标大于0,且原串下标为i的字符与当前子串位置为j的字符不相等的时候,我们要重新匹配,而这个位置是从我们的部分匹配表中的值取出来的,也就是说我们的i对应的原串一直在向后,没有想暴力破解那样在一个一个位置的回溯回来

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. oracle11g insufficient,ORACLE11GORA-01031:insufficientprivileges
  2. python后端工程师 数据爬虫
  3. Linux驱动之平台设备
  4. ffmpeg builds by zeranoe_FFmpeg
  5. eclipse配置PHP自动提示代码
  6. Elasticsearch嵌套查询
  7. 有两个链表a,b,设结点包括学号,姓名。从a链表中删去与b链表中有相同学号的那些结点。
  8. 虚拟机Ubuntu蓝屏闪屏解决方法
  9. mysql手工注入imformation_mysql 简单手工注入
  10. java day27【DQL:查询语句、约束 、多表之间的关系 、范式 、数据库的备份和还原】...
  11. html5 几何酷站,10个值得学习的HTML5+CSS3视觉特效酷站欣赏
  12. 特征码、特征码的概念、特征码的作用、常见的特征码
  13. 【接口篇 / Wan】(6.4) ❀ 02. 单条宽带旁挂软路由优化 ❀ FortiGate 防火墙
  14. 8、Java中XML表示衣服尺码信息的文档编写
  15. golang源代码阅读,sync系列-WaitGroup
  16. Dell R730 xd “CPU 2 M23 VPP PG voltage is outside of range“故障
  17. 甲骨文中间件与主数据管理平台
  18. 如何控制input的输入方向
  19. 压测报502 badgateway问题解决
  20. 勾股定理算斜边用计算机怎么按,勾股定理怎么算斜边

热门文章

  1. webpack最新版本_【每日面经】字节跳动、美团点评、360最新面经速递!
  2. Vue:vue项目npm安装animate.css后动画效果不起作用
  3. crawler4j源码学习(1):搜狐新闻网新闻标题采集爬虫
  4. 机器学习_回归和分类的区别
  5. 图像语义分割(16)-DUpsampling-新型上采样模块:能够聚合丰富特征的数据相关型解码方式(CVPR2019)
  6. LIO-SAM探秘第三章之代码解析(一) --- utility.h + imageProjection.cpp
  7. CVPR2021中的目标检测和语义分割论文汇总
  8. 给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为...
  9. win10 基础之上安装 Linux-Manjaro-Deepin 连夜采坑,快速整理下
  10. linux下wps的字体缺失解决方法