2024年10月kmp算法视频讲解(数据结构与算法——字符串匹配问题(KMP算法))

 更新时间:2024-10-12

  ⑴kmp算法视频讲解(数据结构与算法——字符串匹配问题(KMP算法)

  ⑵数据结构与算法——字符串匹配问题(KMP算法)

  ⑶KMP算法也是比较著名的模式匹配算法。是由D.E.Knuth,J.H.Morrs和VR.Pratt发表的一个模式匹配算法。可以大大避免重复遍历的情况。

  ⑷如果使用暴风算法的话,前面五个字母完全相等,直到第六个字母“f“和“x“不相等。如下图:

  ⑸T=“abcdex”j模式串abcdexnext

  ⑹T=“abcabx“j模式串Tabcabxnext

  ⑺T=“ababaaaba“j———————模式串T———ababaaabanext————

  ⑻T=“aaaaaaaab“j———————模式串T———aaaaaaaabnext————

  ⑼next数组其实就是求解字符串要回溯的位置假设,主串S=“abcababca”;模式串T=“abcdex”,由以上分析得出next数组为,next数组意味着当主串与模式串不匹配时,都需要从第一个的位置重新比较。

  ⑽KMP算法也是有缺陷的,比如主串S=“aaaabcde”,模式串T=“aaaaax”。next的数组就是;

  ⑾当开始匹配时,当i=,j=时,我们发现字符“b“与字符“a”不相等,如上图,j=next=;

  ⑿由于T串的第二、三、四、五位置的字符都与首位“a”相等,那么可以用首位next,那么next数组为{,,,,,};

  ⒀在求解nextVal数组的种情况

  ⒁kmp算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法。KMP算法的关键是根据给定的模式串W,m,定义一个next函数。next函数包含了模式串本身局部匹配的信息。完全掌握KMP算法思想学过数据结构的人,都对KMP算法印象颇深。

  ⒂怎样简单明了的解释KMP算法

  ⒃map根据输入的映射函数,将一个集合映射为另一个集合,比如:输入集合为{,,,,},输入的函数为f(x)=x^,那么输出的集合就是{,,,,}。reduce就是根据输入的归约函数,将集合(一般指map输出的集合归约,比如上面的输出集合是{,,,,},假设我们的归约函数是f(x,y)=x+y,那么reduce的过程就是{,,,}-》{,,}-》{,}-》{}。我们使用Java来描述这个过程:intresult=IntStream.range(,)//获得集合{,,,,}.map(x-》x*x)//映射为{,,,,}.reduce((x,y)-》x+y)//归约.getAsInt();//获得结果System.out.println(result);结果:

  ⒄大一下参加学校ACM预备队集训的时候首次接触KMP算法,当时看了很多介绍文章,仍然不是很理解其实质,只是简单地套模板AC题目,待大二数据结构与算法课堂上再听老师介绍一次,才恍然大悟其实KMP也就是那么回事嘛。但当初为啥看那么多文章都没弄明白呢?正巧最近和朋友聊天时他告诉我他对KMP不是很理解,于是打算自己写一篇文章,巩固自己对KMP的认识,也希望能够帮助更多朋友理解KMP。在开始之前,需要知晓的概念:

  ⒅前缀:以原串串头为自身串头的子串,如的前缀有:后缀:以原串串尾为自身串尾的子串,如的后缀有:

  ⒆注意:字符串前后缀都不包括该串本身

  ⒇给你一个文本串T(TextString)

  ⒈再给你一个模式串P(PatternString)

  ⒉问该模式串是否在文本串中,怎么找?

  ⒊一开始只好分别从文本串与模式串的串头开始逐字母比较

  ⒋二者相同,再比较T串与P串的下一位

  ⒌如果一直这么顺利,两串对应位置的字符总相同,待P串中最后一个字符也匹配完毕,说明该模式串在文本串中存在,耶(??ω??)y超开心,查找结束。但,大多数匹配过程不会如此顺利,在该例中,当匹配进行至

  ⒍很明显,失配了。现在怎么办?按朴素思想,将P串相对T串整体右移一位,重新开始匹配,即

  ⒎但这种算法效率无疑是十分低下的。设T串长度N,P串长度M,则朴素算法时间复杂度为O(MN)

  ⒏已知的重要信息并没有被使用——已匹配的字符串前缀

  ⒐在上例中,当P串最后一个字符匹配失败时,其已有包含七个字符的前缀子串S匹配成功

  ⒑完全可以利用前缀子串S做点什么。观察到在S串

  ⒒中,有相同前后缀,即下图蓝色部分

  ⒓而S串各字符又与T串中对应字符相同,即有

  ⒔当失配发生后,直接将P串右移四位使S串蓝色后缀部分对齐T串中蓝色前缀部分

  ⒕从图中红框部分继续尝试匹配,发现再次失配。这次,已匹配成功的前缀串S为

  ⒖而在该串中没有相同的前后缀,只能将P串串头移至失配处进行比较

  ⒗再次失配。此时前缀串S为空串,只好如朴素算法般将P串整体右移一位,重新开始比较

  ⒘匹配成功。于是又按照之前的步骤往下匹配,直至再次失配或匹配成功

  ⒙后续步骤同上,不再赘述

  ⒚上述示例已展现,KMP算法的精髓在于对已匹配成功的前缀串S的利用

  ⒛在朴素算法中,匹配失败了,T串待匹配字符会回溯

  T串原本已匹配至T=’b’重新开始匹配

  而在KMP算法中,若P早已匹配过,何必再回溯过去重复匹配呢?于是乎,就如问题引入部分展示般

  每当失配发生,我们总是去关注P串中已匹配成功的前缀串S

  因为该前缀串是匹配成功的,说明在T串中必定存在与该前缀串相同的子串,记为S’

  若S串中存在相同前后缀

  则S’串必然也存在此相同前后缀

  所以只需将P串右移四位,使得S串的该相同前缀对齐S’串的该相同后缀

  至于T是否能够匹配另说(当然,本例中一看就知道没匹配上,但通过对前缀串S的利用,成功省去了P串右移一位、两位和三位后的无效匹配

  继续深入思考,给定一个具体的P串,其第N位的前缀串S内容是固定的,则S是否存在相同前后缀、相同前后缀的长度与内容也是确定的。换言之,对于一个具体的P串,当其与给定T串匹配至P失配后,应当使用N之前的哪一位再来与T串进行匹配,以此提高匹配效率,记该数组为Next数组

  定义Next=j表示当P串中第i位失配后,跳转至P串第j位再次尝试匹配

  还是以之前的P串为例,它的Next数组求出来应为

  取下标为例,其前缀串为

  若P=,其余下标对应Next数组值同如此求。

  特别地,规定Next的含义是前N-个已匹配成功的字符构成的前缀串S中,最长相同前后缀长度。所以若在下标为N处匹配失败了,则应前往Next所对应的下标处匹配。

  具体地,以下图所示为例,P失配

  当求出P串Next数组后,便可快速进行与T串的匹配

  现在问题只剩下如何求Next数组,注意到Next数组既然只与P串本身相关,与文本串T无关,故令P串与自身匹配即可求得

  令其与给定文本串相匹配

  失配,于是跳转至P处再次尝试匹配

  再度失配,也必然失配

  本例中该字符串新Next数组为

  失配,于是跳转至P处再次尝试匹配

  省去了之前跳转至P处的无效匹配

  设T串长度M,P串长度N,由于KMP算法不会回溯,分析易知时间复杂度为O(m+n)

  对于P可以取至n中任意值,为最大化匹配效率考虑,总是取最大相同前后缀以提高效率,节省时间

  KMP模式匹配算法KMP算法是一种改进的字符串匹配算法,其关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的明。求得模式的特征向量之后,基于特征分析的快速模式匹配算法(KMP模式匹配算法)与朴素匹配算法类似,只是在每次匹配过程中发生某次失配时,不再单纯地把模式后移一位,而是根据当前字符的特征数来决定模式右移的位数。include“string.h“#include《assert.h》intKMPStrMatching(StringT,StringP,int.N,intstartIndex){intlastIndex=T.strlen()-P.strlen();if((astIndex-startIndex)《)//若startIndex过大,则无法匹配成功return(-);//指向P内部字符的游标inti;//指向T内部字符的游标intj=;//指向P内部字符的游标for(i=startIndex;i《T.strlen();i++){while(P&&j》)j=N;if(P)j++;if(j==P.strlen())return(-j+);//匹配成功,返回该T子串的开始位置}return(-);}

  KMP算法之所以叫做KMP算法是因为这个算法是由三个人共同提出来的,就取三个人名字的首字母作为该算法的名字。其实KMP算法与BF算法的区别就在于KMP算法巧妙的消除了指针i的回溯问题,只需确定下次匹配j的位置即可,使得问题的复杂度由O(mn)下降到O(m+n)。在KMP算法中,为了确定在匹配不成功时,下次匹配时j的位置,引入了next中最长后缀的长度等于相同字符序列的前缀。对于next数组的定义如下:)next=-j=)next)next=其他如:Pababajnext-即next因此KMP算法的思想就是:在匹配过程称,若发生不匹配的情况,如果next=-,则将i右移位,并将j置,继续进行比较。

  一种由Knuth(D.E.Knuth)、Morris(J.H.Morris和Pratt(V.R.Pratt三人设计的线性时间字符串匹配算法。这个算法不用计算变迁函数δ,匹配时间为Θ(n,只用到辅助函数π的值包含了与a无关但在计算δ(q,a时需要的信息。由于数组π只有m个元素,而δ有Θ(m∣Σ∣个值,所以通过预先计算π而不是δ,使得时间减少了一个Σ因子。

  KMP算法真的好难懂啊哪位高手来讲解一下谢谢!

  额这个问题之前没多久给别人解答过,我就直接搬过来了……————————————————————————————————————————好吧~KMP当初我也想了挺久的~很巧妙的算法啊!相必复制百科什么的你也不会看的了所以我手打吧…下面是我的理解~为了解说方便我把长的称为文本串,短的称为目标串~常规的匹配算法是把目标串一位一位地右移,跟文本串比较,而KMP则是跳着右移~举几个例子相信你就懂了————————————————————————————————————————比如有一目标串为ababaca,当前位置匹配了前个,也就是匹配了ababa,后面两个不匹配这说明了文本串当前位置也是ababa显然右移一位是不行的,因为从目标串可以看出(abab)a与a(baba)括号里的内容不相等而右移两位是可能可行的~因为可以看出(aba)ba与ab(aba)括号里的内容是相等的,这意味着移动两位后,目标串前三位aba是肯定匹配的~因为移动前也匹配~————————————————————————————————————————再举一个例子~比如有目标串abcab,当前位置匹配了前两个ab那么就需要右移个位置,因为(ab)cab与abc(ab)括号里内容相同,移动后有可能会匹配~————————————————————————————————————————懂了么?表达能力有限…我也不能讲得更好了…具体代码网上一大堆,《算法导论》里面也有~我当初就是在算导里学会的!如果懂了,希望有追加分啊,手打累死!!!不懂的话,追问吧……

您可能感兴趣的文章:

相关文章