- 1、本文档共58页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
图5-6KMP模式匹配举例(a)主串s和模式串p;(b)在j=7处失配;(c)比较从j=f(7)=4处开始(d)比较从j=f(4)=1开始;(e)匹配成功现在分析Index_KMP算法。该算法中,if(j==-1||s.chs[i]==p.chs[j])语句的执行次数最多,我们以它的执行次数来计算算法的时间复杂度。if语句有两个分支:(1)i++;j++;;(2)j=f[j];。if语句的执行次数是这两个分支执行次数的和。分支(1)中,i的初值为pos(pos≥0),因in,因此,分支(1)最多执行n次。分支(2)中,j的初值为0,执行语句j=f[j]后,由于f[j]j,j在分支(2)中只减不增,只在分支(1)中增1,并只当j≥0时,才会执行分支(2),因此分支(2)的执行次数不会超过分支(1)。所以if语句的执行次数不会超过2n,KMP算法的时间复杂度为O(n)。3.计算失败函数下面讨论失败函数的计算方法。计算f(j)就是对子串p0p1…pj-1求最长的且相等的前缀子串和后缀子串的长度。如果这种计算是费时的,则KMP算法不会给我们带来节省时间的好处。幸运的是我们能够设计出快速计算f(j)的算法。我们知道,总有f(0)=-1。如果已经计算出f(j)(0≤j<m-1),如何计算f(j+1)呢?为了求f(j+1),根据定义,我们需要求得p0p1…pj的最长的且相等的前缀子串和后缀子串的长度k,即max{k|0<k≤j且p0p1…pk-1=pj-k+1pj-k+2…pj}。设f(j)=h,我们有p0p1…ph-1=pj-hpj-h+1…pj-1。(1)若ph=pj,则表明p0p1…ph=pj-hpj-h+1…pj,并且不可能有hh,使得p0p1…ph=pj-hpj-h+1…pj,所以,有f(j+1)=h+1。(2)若ph?pj,则表明p0p1…ph?pj-hpj-h+1…pj。设f(h)=g,考察pg是否与pj相等,如果相等,则意味着p0p1…pg=pj-gpj-g+1…pj,有f(j+1)=g+1,依此类推。这一过程可看成是主串和模式串都是串p的模式匹配过程。由此我们可得到计算失败函数f(j)的递推公式:其中,f1(j)=f(j),fm(j)=f(fm-1(j))。根据上述分析,我们得到程序5-4的计算失败函数值的C程序。【程序5-4】失败函数的C程序。voidFail(Stringp,int*f){ intj=0,k=-1; f[0]=-1; while(jp.Length) if(k==-1||p.chs[j]==p.chs[k]){ j++;k++; f[j]=k; }elsek=f[k];}4.改进的失败函数的C程序失败函数可以通过改进,进一步提高效率。从图5-6可以看出,在第1趟匹配到达失配点时,s7=a,p7=b,s7≠p7,取j=f(j)=4,即下一趟从p4开始与s7继续比较。由于p4=p7=b,因此p4≠s7,此趟回溯到j=4仍然是多余的;同理回溯到j=1也是多余的,可以直接回溯到j=0。这就是说,如果在求得f(j)为k值后,若有pk?pj,可令f(j)=k,否则令f(j)=f(k)。改进的失败函数的例子见表5-2。改进的失败函数的C程序见程序5-5。表5-2改进的失败函数的例子j012345678910Pabcabcabbacf(j)-100-100-105-11【程序5-5】改进的失败函数的C程序。voidFail2(Stringp,int*f){intj=0,k=-1;f[0]=-1;while(jp.Length) if(k==-1||p.chs[j]==p.chs[k]){ j++;k++;if(p.chs[j]==p.chs[k])f[j]=f[k];elsef[j]=k; }elsek=f[k];
文档评论(0)