1.KMP算法

1.1 简介

研究的是子串(必须连续)

int getIndexOf(String str1,String str2);

用的就是KMP算法,不在时返回-1;在时返回在原串中的位置。

时间复杂度是,最起码得遍历完原串。

最坏情况,时间复杂度为.

KMP算法:让前面配过的元素指导后面的匹配,这样就可以加速匹配。

1.2 最长前缀和最长后缀之间的匹配长度

一个字符之前的那个字符串的最长前缀和最长后缀之间的匹配长度(前缀不能包含最后一个字符,后缀也不能包含最前的一个字符)。

1.2.1 举例1

上题中:

  • 长度取1:a≠c
  • 长度取2:ab≠bc
  • 长度取3:abc=abc
  • 长度取4:abca≠cabc
  • 长度取5:abcab不等于bcabc
  • 长度只能取到5

所以答案为3.

1.2.2 举例2

此题中,答案是4

1.2.3 引到next数组

对字符串中的每一位进行计算,得到一个next数组:

1.3 KMP过程

下面,开始用str2的这个next数组进行KMP的过程解释。

假设现在从str1的i位置开始h和str2的0位置开始匹配:

一路都匹配,直到x和y不匹配。

1.3.1 暴力方法

从str1的i+1位置开始,继续和str2的0位置开始匹配。

1.3.2 改进方法

依据y位置的next值,进行加速处理。

假设Y位置的最长前缀和最长后缀的长度如图所示:

将str2中的后缀对应到str1中对应的位置,如下图:

假设str1中相对应的位置起始为j位置,那么接下来就是str1的j位置和str2的0位置开始往后匹配,如下图;

由于str2中前缀标出的部分和后缀中标出的部分是相匹配的,所以str2中前缀的部分和str1中从j位置开始的等长部分也匹配。所以,现在实际上开始匹配的位置是str1中的j位置和str2中的k位置,即比较x和z是否匹配。如图:

1.3.3 举例1

1.3.3 推两次举例

第一次:i是str1中的图中开始的a的位置;j是第一次推之后str1中和str2中0位置比较的位置;

第二次:i是第一次的j,j是第二次推之后,str1中和str2中0位置比较的位置。

第一次看F的next,决定str2推的位置,D和a没匹配上;

此时看a的next决定第二次往后退的位置,2个。比较D和k。没匹配上;

k位置的next为0,所以下一步就是D之后的字符和str2的0位置元素开始匹配。

1.3.4 推的过程的实质

第一次匹配完之后,甲在t位置,乙在F位置,然后甲不动,乙跳到str2中的5位置(即,乙跳到str2中的next[F]的位置),继续和甲指向的元素t进行匹配。

1.3.5 具体匹配过程

  1. 甲指向的字符和乙指向的字符相等:甲++;乙++;
  2. 若不相等:
    1. 乙指向字符对应的next为-1,则说明是str2的起始位置,甲++(即,甲指向的str1中的字符和str2中0位置的字符都不匹配,那就是str1后一个字符继续和str2中0位置的字符比较);
    2. 否则,乙跳到str2中的next[乙]的位置。
  3. 若循环完之后,乙位置超过了str2,则说明匹配成功,返回甲-乙(目前匹配到的位置-乙=str2在str1中的位置);否则返回-1,即不存在。

1.4 next数组的求解

0位置为-1,1位置为0,2位置(若0位置和1位置的字符相等则为1,否则为0)。

其他位置:数学归纳法

目前要求i位置的next值。已知i-1位置的next值为4。则,若前缀串的后一个字符x=b(i-1位置的字符),则i位置的next值为4+1=5。

如果不等:

则看前缀后面的字符x的next值,划分出它的前缀和后缀,然后看x的最长前缀之后的字符和b(i-1位置的字符)是否相等,相等则i位置的next值为x的next值+1,否则继续分。一直到没得分,则i位置的next值才为0;

1.4.1 举例1

1.4.2 举例2

将1.4.1中的i-1位置换为a:

1.2 代码实现

package Classics;public class KMP {public static void main(String[] args) {String str = "abcabcababaccc";String match = "ababa";System.out.println(getIndexOf(str, match));}public static int getIndexOf(String str1,String str2) {if(str1==null||str2==null)return -1;int i1=0;int i2=0;int[] next=getNextArray(str2);char[] chs1=str1.toCharArray();char[] chs2=str2.toCharArray();while(i1<chs1.length&&i2<chs2.length) {if(chs1[i1]==chs2[i2]) {i1++;i2++;}else if(next[i2]>-1){i2=next[i2];//回退}else {//i2在str2的0位置,则需要i1的下一个位置来和str2的0位置(i2位置)匹配i1++;}}return i2==str2.length()?i1-i2:-1;}public static int[] getNextArray(String str2) {if(str2.length()==1)return new int[] {-1};char[] chs=str2.toCharArray();int[] next=new int[chs.length];next[0]=-1;next[1]=0;int i=2;int cn=0;while(i<chs.length) {if(chs[i-1]==chs[cn]) {//x和b相等,则i位置的next值=i-1的next值+1;next[i++]=++cn;}else if(next[cn]>0){cn=next[cn];}else {next[i++]=0;}}return next;}
}

算法练习day16——190404(KMP算法)相关推荐

  1. 【数据结构与算法】字符串匹配 KMP 算法

    单模式串匹配 BF 算法和 RK 算法 BM 算法和 KMP 算法 多模式串匹配算法 Trie 树和 AC 自动机 KMP 算法 KMP 算法是根据三位作者(D.E.Knuth,J.H.Morris ...

  2. 算法(2)KMP算法

    1.0 问题描述 实现KMP算法查找字符串. 2.0 问题分析 "KMP算法"是对字符串查找"简单算法"的优化. 字符串查找"简单算法"是源 ...

  3. 算法:模式匹配之KMP算法

    前言: 昨天看到<算法导论>里的第32章:字符串匹配,说到一个关于字符串匹配的很好的算法--KMP.关于KMP的内存含意以及KMP的来源,不是本文讲述的范畴,请感兴趣的读者自行查阅相关资料 ...

  4. kmp算法的c语言,KMP算法 纯C实现

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 我自己写的KMP算法: int nt[256]; void get_next1(char* T, int next[], int tlen) { int  ...

  5. js实现kmp算法_字符串匹配算法KMP算法

    数据结构中讲到关于字符串匹配算法时,提到朴素匹配算法,和KMP匹配算法. 朴素匹配算法就是简单的一个一个匹配字符,如果遇到不匹配字符那么就在源字符串中迭代下一个位置一个一个的匹配,这样计算起来会有很多 ...

  6. 代码随想录算法训练营第八天|kmp算法

    kmp题目链接 讲解直接看代码随想录就可以了,代码随想录 一.什么是前缀表         前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配. 那么什么是前 ...

  7. 数据结构与算法(5)字符串(BF算法、KMP算法及KMP算法优化)

    目录 一.BF算法(暴力算法) 二.KMP算法 三.KMP算法优化 一.BF算法(暴力算法) 一个一个往后匹配,匹配失败继续从母串下一个和头(子串的头)往后继续匹配. 虽然简单,但是需要较多的时间复杂 ...

  8. 字符串的模式匹配 (朴素模式匹配算法 ,KMP算法)

    字符串的模式匹配 寻找字符串p在字符串t中首次出现的起始位置 字符串的顺序存储 typedef struct {char str[MAXSIZE];int length; }seqstring; 朴素 ...

  9. c语言主范式与编码,超详细!终于搞明白KMP算法

    小伙伴们好久不见,今天将开设"数据结构与算法"专栏,一起梳理一遍硬核课程的重要知识点,那我们开始吧 正文 「字符串匹配」是计算机的基本任务之一,举个栗子,有一个字符串"「 ...

最新文章

  1. EL之DTRFGBT:基于三种算法(DT、RF、GBT)对泰坦尼克号乘客数据集进行二分类(是否获救)预测并对比各自性能
  2. 9-Qt6 QString和QChar
  3. Nacos配置管理-Nacos实现配置管理
  4. 基于 vue2 导航栏透明渐变
  5. C#进阶系列——AOP?AOP!
  6. 最新37网游JS逆向分析
  7. 2009-07-03 19:48 在linux中如何获得微秒精度的时间?-转
  8. Oracle RAC搭建
  9. 原来这些网站功能这么强?做梦都没想到那些软件都不是他的对手!
  10. 虚拟机安装教程win7_VMware15虚拟机软件安装教程
  11. 微积分应用 计算机,微积分及其应用 P.D.Lax等著;林开亮
  12. 内网渗透技术之超越LLMNR/NBNS欺骗的ADIDNS欺骗攻击
  13. flex java blazeds_Flex同Java通信--BlazeDS入门图文详解(上)
  14. wilcoxon符号秩检验matlab,Wilcoxon符号秩统计量的性质.ppt
  15. cesium地图添加坐标点
  16. MybatisPlus进阶(三)——自动填充
  17. 低成本更清晰,下一代视频编码技术将如何实现这一目标?
  18. Eclipse控制台中的中文输出乱码问题
  19. 【软件技术基础】01
  20. python 表示2的n次方

热门文章

  1. 5.34. PECL FAQ
  2. 从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么
  3. ASP.NET MVC开发,编辑页面和添加页面基本相同,我们控制器 Add Edit是共用同一个View吗?...
  4. AutoCAD VBA对齐对象
  5. 宽带拨号时出现错误列表
  6. if else复合语句
  7. Go中的函数也是一种数据类型,可以赋值给一个变量
  8. linux deepin/ubuntu安装flameshot火焰截图
  9. Ubuntu21.04 deepin-wine 微信输入中文乱码,黑块,和多余窗口问题解决
  10. golang变量定义细节及beego环境搭建细节记录