数据结构——串剖析.ppt

数据结构——串剖析

while (ks.length)(jt.length) { if (*p==*q) { p++ ; q++ ; k++ ; j++ ; } else { k=k-j+1 ; j=0 ; q=t.str ; p=s.str+k ; } /* 重新设置匹配位置 */ } if (j==t.length) return(k-t.length) ; / * 匹配,返回位置 */ else return(-1) ; /* 不匹配,返回-1 */ } //End * 该算法简单,易于理解。在一些场合的应用里,如文字处理中的文本编辑,其效率较高。 该算法的时间复杂度为O(n*m) ,其中n 、m分别是主串和模式串的长度。通常情况下,实际运行过程中,该算法的执行时间近似于O(n+m) 。 理解该算法的关键点 当第一次sk≠tj时:主串要退回到k-j+1的位置,而模式串也要退回到第一个字符(即j=0的位置)。 比较出现sk≠tj时:则应该有sk-1=tj-1,…,sk-j+1=t1, sk-j=t0 。 * 该改进算法是由D.E.Knuth ,J.H.Morris和 V.R.Pratt提出来的,简称为KMP算法。其改进在于: 每当一趟匹配过程出现字符不相等时,主串指示器不用回溯,而是利用已经得到的“部分匹配”结果,将模式串的指示器向右“滑动”尽可能远的一段距离后,继续进行比较。 例:设有串s=“abacabab” ,t=“abab” 。则第一次匹配过程如图4-2所示。 图4-2 模式匹配示例 s=“a b cbb” i=3 || || ≠ 匹配失败 t=“a b b” j=3 * 在i=3和j=3时,匹配失败。但重新开始第二次匹配时,不必从i=1 ,j=0开始。因为s1=t1,t0≠t1,必有s1≠t0,又因为t0=t2,s2=t2,所以必有s2=t0。由此可知,第二次匹配可以直接从i=3 、j=1开始。 总之,在主串s与模式串t的匹配过程中,一旦出现si≠tj ,主串s的指针不必回溯,而是直接与模式串的tk(0≦kj进行比较,而k的取值与主串s无关,只与模式串t本身的构成有关,即从模式串t可求得k值。) * 不失一般性,设主串s=“s1s2…sn” ,模式串t=“t1 t2 …tm” 。 当si≠tj(1≦i≦n-m,1≦jm,mn)时,主串s的指针i不必回溯,而模式串t的指针j回溯到第k(kj)个字符继续比较,则模式串t的前k-1个字符必须满足4-1式,而且不可能存在k’k满足4-1式。 t1t2…tk-1= si-(k-1) si-(k-2) … si-2 si-1 (4-1) 而已经得到的 “部分匹配”的结果为: tj-(k-1) tj-k… tj-1=si-(k-1) si-(k-2) … si-2 si-1 (4-2) 由式(4-1)和式(4-2)得: t1t2…tk-1=tj-(k-1) tj-k… tj-1 (4-3) 该推导过程可用图4-3形象描述。实际上,上式(4-3)描述了模式串中存在相互重叠的子串的情况。 * 图4-3 KMP算法示例 主串s i 模式串t k j 0 当j=1时 Max{k|1kj∧t1t2…tk-1=tj-(k-1) tj-k… tj-1 } 该集合不空时 1 其它情况 next[j]= 定义next[j]函数为 * 在求得了next[j]值之后,KMP算法的思想是: 设目标串(主串)为s,模式串为t ,并设i指针和j指针分别指示目标串和模式串中正待比较的字符,设i和j的初值均为1。若有si=tj,则i和j分别加1。否则,i不变,j退回到j=next[j]的位置,再比较si和tj,若相等,则i和j分别加1。否则,i不变,j再次退回到j=next[j]的位置,依此类推。直到下列两种可能: (1) j退回到某个下一个[j]值时字符比较相等,则指针各自加1继续进行匹配。 (2) 退回到j=0,将i和j分别加1,即从主串的下一个字

文档评论(0)

1亿VIP精品文档

相关文档