KMP算法是一种神奇的字符串匹配算法,在对 超长字符串 进行模板匹配的时候比暴力匹配法的效率会高不少。接下来我们从思路入手理解KMP算法。

在对字符串进行匹配的时候我们最容易想到的就是一个个匹配,类似下面这种:

换成Java代码就是:

public static boolean bfSearch(String pattern,String txt){

if (txt.length() < pattern.length())

return false;

for (int i = 0; i < txt.length(); i++) {

boolean flag = false;

for (int j = 0; j < pattern.length(); j++) {

if (i+j>=txt.length())

return false;

if (txt.charAt(i+j)!=pattern.charAt(j)){

flag = true;

}

}

if (!flag){

return true;

}

}

return false;

}

暴力匹配算法的时间复杂度为O(n*m),n为模板字符串,m为目标字符串,在处理复杂字符串时毫无疑问效率会非常低,由此诞生了KMP算法(时间复杂度为O(m+n) )。

以上面gif图中的两个字符串

​ txt = “aaacaaab”

​ pat = “aaab”

​ 为例我们来说一下KMP算法的思路。个人能力有限,您可以先行观看此视频去简单学习KMP的基本原理。

简单原理:构建状态转移数组,当遇到无法匹配的字符时根据状态转移数组进行回溯,以达到减少遍历次数的目的。

1.首先构建状态转移数组:

对匹配模式字符串进行遍历

从左向右遍历,如果 i 和 j(见源码)所指向的元素相同,则将此状态(j所指向的元素位置)进行保存

最后保存的数组是一个Int类型的状态码数组,每个元素的含义是回溯时模板字符串(pattern)的状态。

2.构建完成后通过状态转移数组和匹配模式字符串对传入的目标字符串进行匹配。过程如下:

对目标字符串进行遍历,检索相同的字符元素。

如果遇到不同的字符元素,根据 J(模板字符串的指针)所在的位置依靠状态转移数组来回溯遍历状态。并在回溯后继续进行匹配。

3.源码如下:

import java.util.Arrays;

public class KMP {

private int[] patArray; // 状态转移数组

private final String pattern;// 匹配模式字符串

public static boolean bfSearch(String pattern,String txt){

if (txt.length() < pattern.length())return false;

for (int i = 0; i < txt.length(); i++) {

boolean flag = false;

for (int j = 0; j < pattern.length(); j++) {

if (i+j>=txt.length())return false;

if (txt.charAt(i+j)!=pattern.charAt(j)){

flag = true;

}

}

if (!flag){

return true;

}

}

return false;

}

KMP(String pat) { // 通过匹配模式字符串构建对象

this.pattern = pat;

patArray = new int[pattern.length()]; // 创建状态转移数组

int j = 0;

for (int i = 1; i < pattern.length(); ) {

if (pattern.charAt(i) == pattern.charAt(j)){

// 如果i和j指向的字符相同,则将此状态进行保存

patArray[i++] = ++j; // 保存的同时移步下一位

}else {

// 如果 i 和 j 指向的字符不相同,则保持i不动,回溯j

// 如果回溯后的j指向的字符与i相同,则将此时的状态进行保存

if (j <= pattern.length() - 1 && j >0) {

j=patArray[--j]; // 回溯j

if (pattern.charAt(i) == pattern.charAt(j)) {

// 如果回溯后相同,则保存状态

patArray[i++] = ++j;

}

}else if (j == 0) {

// 如果回溯到头,则保存为0状态

patArray[++i] = 0;

}

}

}

}

boolean search(String txt){

int j = 0;

for (int i = 0; i < txt.length(); i++) {

// 对输入的字符串进行模式匹配

if (txt.charAt(i) != pattern.charAt(j)){

// 如果匹配不成功,则根据状态数组对j进行状态更改

if (j>0)--j; // 回溯

j = patArray[j];

}else {

++j; // 匹配成功则进入下一个状态

}

if (j == pattern.length()-1){ // 如果成功匹配,返回true

return true;

}

}

return false;// 匹配不成功

}

}

后续的一些思考:

在对比较短的目标字符串而言,毫无疑问使用暴力法的效率(时间复杂度为O(M*N)会快一点,而当目标字符串的长度非常长以后,暴力匹配的效率就会大打折扣。

对于非常长的字符串来说,KMP的O(M+N)的效率相对来说就会非常高。

以上就是java 实现KMP算法的详细内容,更多关于java 实现KMP算法的资料请关注WEB开发者其它相关文章!

java实现kmp_java 实现KMP算法相关推荐

  1. Java 字符串匹配的KMP算法

    package Four;import java.util.Scanner;/**** 字符型的kmp算法* @author bai* 描述:* 给你一个文本串,再给你一个模式串,* 文本串中有多少个 ...

  2. Java数字匹配的kmp算法

    package Four; /**** 研究kmp算法(数字之间的匹配模式)* @author bai* 题目描述:给你两个数字序列,你的任务是在序列a中* 找到和序列b完全匹配的子串,如果有多个匹配 ...

  3. 【Java数据结构与算法】第十八章 动态规划和KMP算法

    第十八章 动态规划和KMP算法 文章目录 第十八章 动态规划和KMP算法 一.动态规划 1.介绍 1.爬楼问题 2.扔鸡蛋问题 3.背包问题 二.KMP算法 1.引入 2.介绍 2.代码实现 一.动态 ...

  4. 【LeetCode】图解KMP算法

    文章目录 前言 1.简介 2.图解KMP思想 2.1.串的匹配 2.2.寻找相同前后缀 3.真枪实战 3.1.题目描述 3.2.示例 3.3.提示 3.4.思路 3.5.具体实现 3.6.测试结果 前 ...

  5. 详解KMP算法原理,以及完整java与C++实现

    点击此处学习更多算法与通信知识 作者 | labuladong 来源 | labuladong KMP 算法(Knuth-Morris-Pratt 算法)是一个著名的字符串匹配算法,效率很高,但是确实 ...

  6. 经典KMP算法C++与Java实现代码

    前言: KMP算法是一种字符串匹配算法,由Knuth,Morris和Pratt同时发现(简称KMP算法).KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的.比 ...

  7. KMP算法中next数组的理解与算法的实现(java语言)

    KMP 算法我们有写好的函数帮我们计算 Next 数组的值和 Nextval 数组的值,但是如果是考试,那就只能自己来手算这两个数组了,这里分享一下我的计算方法吧. 计算前缀 Next[i] 的值: ...

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

    目录 暴力匹配 KMP算法 暴力匹配 暴力算法就是 普通模式的匹配算法 bf算法就是将目标的字符串 的第一个字符与模式的第一个字符进行匹配,相等的话就继续比较第二个字符是否是匹配的,依次进行下去,如果 ...

  9. 模式匹配(Java)——烤馍片算法(KMP算法)

    模式匹配(Java) 模式匹配 模式匹配是数据结构中字符串的一种基本运算. 由于字符串我们学习过了,大部分操作都比较清楚,但是模式匹配相对来说操作稍微有些难度,所以我们在这里简单的进行讲述. 模式匹配 ...

最新文章

  1. NetBeans使用介绍(五)
  2. 研究生再次大幅扩招!高校能否承载?教育部最新表态来了
  3. many-to-many
  4. JQuery.Ajax 错误调试帮助信息
  5. 超图桌面版根据现有数据源制作一幅地图简单操作
  6. 如何进行MaxCompute 用户认证?
  7. Google Drive的linux客户端使用(还没弄完)
  8. 预售┃连锁反应装置积木好玩到尖叫!
  9. 牛客网在线编程:分苹果
  10. 关于程序、进程和线程
  11. win10树莓派改ip_在树莓派2上安装 Windows 10
  12. I/O重定向的原理和实现
  13. 汉字字符内码查询_计算机等级考试查询系统
  14. 大漠综合工具取点阵显示不全_利用pyfolio工具评价回测资金曲线
  15. php跳转方式带rere_PHP利用REFERER根居访问来地址进行页面跳转
  16. 安装spinningup填坑ERROR: Could not build wheels for mpi4py which use PEP 517
  17. “十步杀一人,千里不留行。事了拂衣去,深藏功与名。”
  18. 数据科学与机器学习案例之汽车目标客户销售策略研究
  19. 【Python基础】3-语法进阶
  20. 静态代码分析工具清单:开源篇

热门文章

  1. 20169210 2016-2017-2《网络攻防实践》第五周作业
  2. 扩展progress_timer的计时精度
  3. Java 中自定义时间格式
  4. 持续集成及部署利器:Go
  5. 黑马程序员--里氏转换
  6. 项目展示-新浪微博客户端
  7. ASP.Net 多虚拟目录Web应用程序 实现Session共享
  8. pix4d无人机影像处理_让无人机创造更大价值?你还差一个Pix4D培训会!
  9. 简单循迹小车实验心得_智能循迹小车总结 智能循迹小车报告.doc
  10. 普开数据第15届全国高校师资班(青海西宁)