字符串匹配算法研究(一)
上星期拜读了2004年中国IOI集训队中朱泽园(当时就读南京市外国语学校)的一篇论文《多串匹配算法及启示》,并将其中的部分算法在理解的基础上用C++和Java做了实现。现将本人的理解与代码帖出,请读者不吝赐教。
首先我把该算法要解决的问题重新描述一下:即给定m个长度不等的模式串S1,S2,...,Sm以及一篇长度为n的正文T,求min({s|整数s∈[0,n-1],且存在整数a∈[1,m],使得T.subString(s,Sa.length-1)=Sa})。例如,当正文T=abcdefgh,S1=cdefg,S2=efg,则s=2。(因为S1出现在T下标为2的子串处,S2出现在T下标为4的子串处,min(2,4)=2)。
对于解决该问题的实际意义,论文作者已表述得十分清楚:“含逻辑关键字的搜索引擎是这个问题的实际应用。医学家们在DNA序列中,搜索可能为变异的几种模式,也是这类问题的典型。因此用有效算法解决该问题
能大大提高各行业的工作效率。”
对于如何解决该问题,作者首先给出了最容易相到的枚举法及其优化。由于该想法太过简单,只要稍具编程基础的人都能想到因此我就不再讨论了。总而言之,用枚举法解决该问题的时间复杂度为O(n*sum({Si.length|i=1,2,...,n}))。而对于问题的规模而言,明显枚举法是力不从心的。
为了有效地解决该问题,作者先将问题简化。即当模式串只有一个时,多串匹配问题就变成了单串匹配问题。对于单串匹配作者发现了一现成的算法:kmp(Knuth-Morris-Pratt)算法。kmp算法的功能如下:
输入:模式串P(长度为m),正文T(长度为n)
输出:集合{s|整数s∈[1,m+n-1]且T.subString(s,m-1)=P}
kmp算法的主体思想是先给出模式串的前缀函数(定义:Pi(j)=max{j|P.subString(0,j)=P.subString(i-j,i),j∈[0,i]}),对模式串进行预处理,之后在拿原文和模式串比较时,可根据模式串的前缀函数来移位,减少不必要的比较次数。现给出代码:










































































