- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
字符串的模式匹配算法
在前面的图文中,我们讲了“串”这种数据结构,其中有求“子串在主串中的位置”(字符串的模式匹配)这样的算法。解决这类问题,通常我们的方法是枚举从A串(主串)的什么位置起开始与B串(子串)匹配,然后验证是否匹配。假设A串长度为n,B串长度为m,那么这种方法的复杂度是O(m*n)的。虽然很多时候复杂度达不到m*n(验证时只看头一两个字母就发现不匹配了),但是我们有许多“最坏情况”,比如:A=“aaaaaaaaaaaaaaaaaaaaaaaaab”,B=“aaaaaaaab”。大家可以忍受朴素模式匹配算法(前缀暴力匹配算法)的低效吗?也许可以,也许无所谓。有三位前辈D.E.Knuth、J.H.Morris、V.R.Pratt发表一个模式匹配算法,最坏情况下是O(m+n),可以大大避免重复遍历的情况,我们把它称之为克努特-莫里斯-普拉特算法,简称KMP算法。?假如,A=“abababaababacb”,B=“ababacb”,我们来看看KMP是怎样工作的。我们用两个指针i和j分别表示,。也就是说,i是不断增加的,随着i的增加j相应地变化,且j满足以A[i]结尾的长度为j的字符串正好匹配B串的前j个字符(j当然越大越好),现在需要检验A[i+1]和B[j+1]的关系。?例子:S=“abcdefgab”T=“abcdex”对于要匹配的子串T来说,“abcdex”首字符“a”与后面的串“bcdex”中任意一个字符都不相等。也就是说,既然“a”不与自己后面的子串中任何一字符相等,那么对于主串S来说,前5位字符分别相等,意味着子串T的首字符“a”不可能与S串的第2到第5位的字符相等。朴素算法步骤2,3,4,5的判断都是多余,下次的起始位置就是第6个字符。?例子:S=“abcabcabc”T=“abcabx”如果T串后面也含有首字符“a”。对于开始的判断,前5个字符完全相等,第6个字符不等,此时,根据刚才的经验,T的首字符“a”与T的第二位字符“b”、第三位字符“c”均不等,所以不需要做判断,朴素算法步骤2,3都是多余。因为T的首位“a”与T第四位“a”相等,第二位的“b”与第五位的“b”相等。而第四位的“a”与第五位的“b”已经与主串S中的相应位置比较过了,是相等的,因此可以断定,T的首字符“a”、第二位的字符“b”与S的第四位字符和第五位字符也不需要比较了,下次的起始位置就是6,T的起始位置就是第3个字符。?对比这两个例子,可知两种情况下主串当前位置的都是第6个字符。要考虑的变化就是子串的下标j值了。通过观察也可发现,我们屡屡提到了T串的首字符与自身后面字符的比较,发现如果有相等字符,j值的变化就会不相同。也就是说,这个j值的变化与主串其实没什么关系,关键就取决于T串的结构中是否有重复的问题。?下面按照程序的方式来介绍,字符串第一个字符的下标为0。由于T=“abcdex”,当中没有任何重复的字符,所以j就由5变成了0。由于T=“abcabx”,前缀的“ab”与后面“x”之前串的后缀“ab”是相等的。因此j就由5变成了2。因此,我们可以得出规律,j值的多少取决于当前字符之前的串的前,后缀的相似度。?我们把T串各个位置的j值的变化定义为一个数组next,那么next的长度就是T串的长度。于是我们可以得到下面的定义:?起始字符 next[0] = -1;如果后面没有与起始字符相同的字符则next[i] = 0;如果后面有与起始字符相同的字符则next[i] = -1;与前缀进行匹配,匹配完毕的后一位的j值记录匹配字符的个数。其他next[i] = 0;即next[i]的值表示,第i位不同时,j的取值。具体构造方法查看后面代码。?例子:T=“abcdex”Next = -100000?例子:T=“abcabx”Next = -100-102?例子:T=?“aaaaaaaab”Next = -1-1-1-1-1-1-1-17?例子:T =“ababacb”Next = -10-10-130讲完原理之后,我们利用策略模式作为解决相同问题利用不同算法的解决方案。namespace?StringMatching{????public?abstract?class?StringMatchingStrategy??? {???????public?abstractint?StringMatchingAlgorithm(string?source,?stringsubstr);??? }}namespace?StringMatching{????public?class?KmpMatching:?StringMatchingStrategy??? {????????privateint[] GetNext(stringsubstr)??????? {????????
文档评论(0)