您的位置:首页 > 其它

两个字符串模式匹配的算法

2010-12-13 20:45 423 查看
今天看了一下查找子串在某个文本中出现的位置的两个算法。一个是Karp-Rabin算法,另外一个是Knuth-Morris-Pratt算法。

先来说明一下这个Karp-Rabin算法。该算法提出了一个简单的子串位置查询的方法,区别于brute force方法的O(m*n)的时间复杂度,该算法在最坏情况下的时间复杂度是O(m*n),其平均复杂度为O(m+n)。其中m为子串的长度。n为文本的长度。该算法使用hash函数来检查两个序列。从而查找出子串在文本中出现的位置。其中hash function需要具有以下属性:

1、能够很快地计算出来;

2、严格区分出不同的字符串;

3、在已知hash(y[i ... i+m-1])的情况下可以很容易地求解出hash(y[i+1 ... i+m]),具体的求解式为:

hash(y[i+1 ... i+m]) = rehash(y[i],y[i+m],hash(y[i...i+m-1]);

对长度为m的子串w,定义hash(w) = (w[0]*2m-1+w[1]*2m-2+...+w[m-1])mod q

其中q为一个大的素数。另外,我们定义rehash(a,b,h) = (h-a*2m-1)*2+b)mod q .

在查找模式串w的过程中,hash(w)需要与hash(y[i..i+m-1])进行比较,其中(0<=i<n-m)。如果发现有hash值相等的,则需要对x=y[i..i+m-1]进行逐个字符的比较,以确定其是否相同。

如: w= ing.

则hash(w) = 105*22+110*2+103 = 743 按照字符的ASCII码进行计算的。

y = s t r i n g m a t c h i n g

hash = 806 797 776 743 678 585 443 746 719 766 709 736 743

这样,如果在文本串中有和子串相同hash值的字符串,则逐字符地比较这两个hash函数值相同的字符串,如果相同,则在文本中找到子串,如果不同,则文本中没有要找的子串。 该方法相比于brute force算法上面有改进,但其最坏的时间复杂度却和brute force算法相同。

下面我们引入的Knuth-Morris-Pratt算法,该算法查找子串的时间复杂度是线性的。

假定x[0...m-1]和文本字符y[i...i+m-1]对齐,假定它们的第一个不匹配的字符是y[i+j]和x[j] (1<j<m)。则可以推出y[i...i+j-1] = x[0...j-1] = u并且a = y[i+j] != x[j] = b。当移动下标重新进行比对的时候,很显然,我们希望x的前缀v和文本的u的部分后缀匹配。此外,如果我们能够避免其他立马可能出现的不匹配字符的话,x串的前缀v后面紧跟的字符肯定不能是b了。

今天先写到这里了,这两个算法现在只是一个初步的了解,刚开始看这篇文章,关于算法的描述基本上是翻译了以下“Review Pattern Matching and Text Compression Algorithms”这篇文章。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: