KMP算法浅析
时间:2022-04-29
本文章向大家介绍KMP算法浅析,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
具体参见: KMP算法详解
背景:
KMP算法之所以叫做KMP算法是因为这个算法是由三个人共同提出来的,就取三个人名字的首字母作为该算法的名字。其实KMP算法与BF算法的区别就在于KMP算法巧妙的消除了指针i的回溯问题,只需确定下次匹配j的位置即可,使得问题的复杂度由O(mn)下降到O(m+n)。
KMP算法的思想就是:在匹配过程称,若发生不匹配的情况,如果next[j]>=0,则目标串的指针i不变,将模式串的指针j移动到next[j]的位置继续进行匹配;若next[j]=-1,则将i右移1位,并将j置0,继续进行比较。 在KMP算法中,为了确定在匹配不成功时,下次匹配时j的位置,引入了next[]数组,next[j]的值表示P[0...j-1]中最长后缀的长度等于相同字符序列的前缀。 对于next[]数组的定义如下: 1) next[j]=-1 j=0 2) next[j]=max k:0<k<j P[0...k-1]=P[j-k,j-1] 3) next[j]=0 其他 如: P a b a b a j 0 1 2 3 4 next -1 0 0 1 2 即next[j]=k>0时,表示P[0...k-1]=P[j-k,j-1]
next的求解程序如下:
1 private int[] next(String str){
2 if(str == null || str.length() == 0){
3 return null ;
4 }
5 int [] next = new int [str.length()] ;
6 next[0] = -1 ;
7 int lastSame = 0 ;
8 for(int i = 1 ; i < str.length() ; i++ ){
9 char temp = str.charAt(i) ;
10 next[i] = lastSame ;
11 if(temp == str.charAt(lastSame)){
12 lastSame++ ;
13 }else{
14 lastSame = 0 ;
15 }
16 }
17
18 return next ;
19 }
通过next采用KMP算法判断是否匹配的代码如下:
1 /**
2 * 若src包含dest子串,则返回src中dest子串出现的位置(首字符的位置),
3 * 若不包含,则返回-1
4 * @param src
5 * @param dest
6 * @return
7 */
8 private int KMPmatch(String src, String dest){
9 if(src == null || dest == null || src.length() < dest.length()){
10 return -1 ;
11 }
12 int [] next = next(dest);
13 int i = 0 ;
14 int j = 0 ;
15 while(i < src.length()){
16 if((j == -1) || (src.charAt(i) == dest.charAt(j))){
17 i++ ;
18 j++ ;
19 }else{
20 j = next[j] ;
21 }
22
23 if(j == (dest.length())){
24 return i-j ;
25 }
26 }
27
28 return -1 ;
29 }
- WCF版的PetShop之二:模块中的层次划分[提供源代码下载]
- 我的WCF之旅(3):在WCF中实现双工通信
- 我的WCF之旅 (11): 再谈WCF的双向通讯-基于Http的双向通讯 V.S. 基于TCP的双向通讯
- 更新弹幕系统的心得体会
- 我的WCF之旅(6):在Winform Application中调用Duplex Service出现TimeoutException的原因和解决方案
- 我的WCF之旅 (11): 再谈WCF的双向通讯-基于Http的双向通讯 V.S. 基于TCP的双向通讯
- 我的WCF之旅(6):在Winform Application中调用Duplex Service出现TimeoutException的原因和解决方案
- 扩展mysql - 手把手教你写udf
- scrapy初体验 - 安装遇到的坑及第一个范例
- Linux性能监控 - CPU、Memory、IO、Network
- 浅谈UDP(数据包长度,收包能力,丢包及进程结构选择)
- WCF版的PetShop之三:实现分布式的Membership和上下文传递
- “高并发”问题如何解决?腾讯云一分钟配置的“黑科技”帮您
- 初探JavaScript(三)——JS带我"碰壁"带我飞
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Docker_001
- Docker_002
- [PyQt Tutorial]2.一个Hello World程序
- Oracle设置开机自启
- Go_学习之Docke容器
- zabbix 监控项
- [PyQt Tutorial]4.使用Qt Designer
- [PyQt Tutorial]5.Signals & Slots(信号与槽)
- Docker数据共享与持久化
- [PyQt Tutorial]6.Layout Management(布局管理)
- Kubernetes入门
- [PyQt Tutorial]7.QDialog 类
- kubeadm快速部署kubernetes集群
- [PyQt Tutorial]8.QMessageBox
- Tomcat_01_简介