《KMP算法详解-转帖.docx》由会员分享,可在线阅读,更多相关《KMP算法详解-转帖.docx(10页珍藏版)》请在优知文库上搜索。
1、KMP算法详解转帖2010-02-2412:05个人觉得这篇文章是网上的介绍有关KMP算法更让人简洁理解的文章的确说得很“具体”,耐性地把它看完确定会有所收获的另外有关模式函数值nexti的确仃很多版本啊.在另外些面对对象的算法描述书中也仃失效函数f(j)的说法,其实是个意思,Pnextj=f(j-l)b不过还是nextj这种表示法好理解啊:KMP字符串模式匹配详解KMP字符串模式匹配通俗点说就是一种在一个字符印中定位另一个串的高效第法。简洁匹配算法的时间困难度为0(m*n);KMP匹配兑法。可以证明它的时间困难度为0(m+n).。.简洁匹配算法先来看一个简洁匹配算法的函数:intIndexB
2、F(ChHrS,charT,inipos)I/*若用S中从第POS(S的下标OWpOSGtr1.ength(三)个字符起存在和申T相同的子串,则称匹配胜利,返回第一个这样的子串在串S中的下标,否则返回-1*/inti=pos,j=0:while(Si+j!=0,UTj!=,0,)if(Si+j=Tj)j+;/接着比较后一字符else(i+;j=0:/重新起先新的一轮匹配)if(Tj=,0,)returni;/匹配胜利返回下标elsereturnT;串S中(第pos个字符起)不存在和串T相同的子串)/IndeX_BF此算法的思想是直截了当的:将主串S中某个位置i起始的了用和模式串T相比较。即从j
3、=0起比较Si+j与TlJ,若相等,则在主申S中存在以i为起始位置匹配胜利的可能性,接着往后比较(j逐步增1),直至与T串中最终一个字符相等为止,否则改从S串的卜.一个字符起重新起先进行卜.一轮的匹配”,即将用T向后滑动位,即i增1,而j退回至0,重新起先新轮的匹配,例如:在申S=abcabcabdabba”中查找T=abcabd(我们可以假设从下标0起先):先是比较S0和T0是否相等,然后比较SI:1和Tl是否相等我们发觉始终比较到S5和T5才不等。如图:当这样个失配发生时,T下标必需回溯到起先,S下标回溯的长度与T相同.然后S下标增1,然后再次比较。如图:这次立即发生了失配,T下标又回溯到
4、起先,S下标增I,然后再次比较。如图:这次立即发生/失配,T下标又回溯到起先,S下标增I,然后再次比较.如图:乂次发生了失配,所以T下标乂回溯到起先,S下标增1,然后再次比较。这次T中的全部字符都和s中相应的字符匹配函数返I可T在S中的起始下标3。如图:二.KMP匹配算法还是相同的例子,在S=abcabcabdabba”中查找T=abcabd”,假如运用KMP匹配算法,当第次搜寻到S5和T5不等后,S下标不是回溯到1,T下标也不是回溯到起先,而是依据T中T5=-d的模式函数值(ncxt5=2,为什么?后面讲),干脆比较S5和T2是否相等,因为相等,S和T的下标同时增加:因为乂相等,S和T的下标
5、乂同时增加。最终在S中找到了T。如图:KMP匹配算法和简洁匹配算法效率比较,个极端的例子是:在S=ttAAAAAA-AAB“(100个A)中查找T=,AAAAAAAAB,t,简洁匹配算法每次都是比较到T的结尾,发觉字符不同,然后T的下标回溯到起先,S的下标也要回溯相同长度后增1,接着比较。假如运用KMP匹配算法,就不必回溯.对于般文稿中用的匹配,简洁匹配算法的时间困难度可降为O(In-n),因此在多数的实际应用场合下被应用.KYP算法的核心思想是利用已经得到的部分匹配信息来进行后面的匹配过程。看前面的例子。为什么T5k=d的模式函数值等于2(nexc5=2),其实这个2表示T5=d的前面有2个
6、字符和起先的两个字符相同,IlT5=fd不等于起先的两个字符之后的第1个字符(T2=c).如图:也就是说,假如起先的两个字符之后的第三个字符也为d,那么,尽管T5=d的前面有2个字符和起先的两个字符相同,T5=三(T的模式函数值也不为2,而是为0。前面我说:在S=”abcabcabdabba”中查找T=abcabd”,假如运用KMP匹配算法,当第次搜寻到S5和T5不等后,S下标不是回溯到1.T下标也不是回溯到起先,而是依据T中T5=d的模式函数值,干脆比较S5和T2是否相等.。.为什么可以这样?刚才我又说:“(next5=2),其实这个2表示T5三=d的前面有2个字符和起先的两个字符相同.请看
7、图:因为,S4=T4,S3=T3,依据next5=2,有T3=T0,T4=T1,所以S3=T0,S4T1(两对相当于间接比较过了),因此,接卜.来比较S5和T2J是否相等。有人可能会问:S3flT0,S4和TuJ是依据nexl5=2间接比较相等,那S1.flT0,S2和T和之间又是怎么跳过,可以不比较呢?因为SO=TO,S1=T1,S2=T2,而T0!=T1,Tl!=T2,=S0!=S1,S1!=S2,所以Sl!=T0,S2!=T0.还是从理论上间接比较了。有人疑问乂来了,你分析的是不是特殊轻况啊。假设S不变,在S中搜寻T=abaabd”呢?答:这种状况,当比较到S2和T2时,发觉不等,就去看
8、nexl2的值,next发=T,意思是S2已经和T0间接比较过了,不相等,接下来去比较S3和T接吧。假设S不变,在S中搜寻T=abbabd”呢?答:这种状况当比在到S2和T2时,发觉不等,就去看next2的值,next2=0,意思是S2己经和T2比较过了,不相等,接卜.来去比较S2和T0吧。假设S=abaabcabdabba”在S中搜寻T=abaabd”呢?答:这种状况当比较到S5和T5时,发觉不等,就去看next5的值,next5=2,意思是前面的比较过其中,S5的前面有两个字符和T的起先两个相等,接下来去比较S5和T吧总之,有了用的next值,切搞定。那么,怎么求串的模式函数值nextn呢
9、?(本文中next值、模式函数值、模式值是个意思。)三.怎么求串的模式值nexln定义:(1) next0三-1意义:任何串的第一个字符的模式值规定为-1.(2) ncxtj=-1意义:模式小T中下标为j的字符,假如与首字符相同,且的前面的lk个字符与开头的lk个字符不等(或者相等但kI=T1.jD(IWkQ).如:T=abCabCad”则next6=T,因T3=T6(3)nextj=k意义:模式串T中下标为j的字符,假如的前面k个字符号开头的k个字符相等,且Tj!=Tklkj).BPTt0TlT2.,Tk-1=Tj-kTj-k+lTj-k+2Tj-l且Tj!=Tk.(lkj);(4)next
10、j=O意义:除(1)(2)(3)的其他状况。举例:01)求T=abcac”的模式函数的值。next0=T依据(1)因(3)仃l=kj;不能说,因(3)有l=k0但kn,表示,Sm的前k个字符与T中的起先k个字符已经间接比较相等r,下一次比较sm和Tk相等吗?4. 其他值,不行能。四.求串T的模式值nextn的函数说这么多,是不是觉得求串T的模苴值nextn很困难呢?要叫我写个函数出来,目前来说,我宁愿去登天.好在有现成的函数,当时独创KMP算法,写出这个函数的先辈,令我佩服得六体投地。我等后生小子,理解起来,都要反贪琢磨。下面是这个函数:voidget_nextval(constchar*T,intnext)(求模式串T的next函数值并存入数组next。intj=0,k=-1:ncxt0=-1:whiIe(TCj/*+!*/!=0,)(if(k=-1HTj=Tk)+j;+k;if(Tj!=Tk)nextj=k;elsenextj=nextk:/ifelsek=nextk;/while这里是我加的显示部分/for(inti=0:ij;i+)/coutnexli;/