您的位置:首页 > 其它

字符串匹配算法 之 (Horspool )Boyer-Moore-Horspool

2016-07-29 19:15 274 查看

简介

Horspool是后缀搜索,大家都从左往右匹配,它反着来。也就是搜索已读入文本中是否含有模式串的后缀;如果有,是多长,显然,当后缀长度等于模式串的长度时,我们就找到了一个匹配。

Horspool算法思想:模式串从右向左进行匹配。对于每个文本搜索窗口,将窗口内的最后一个字符与模式串的最后一个字符进行比较。如果相等,则继续从后向前验证其他字符,直到完全相等或者某个字符不匹配。然后,无论匹配与否,都将根据在模式串的下一个出现位置将窗口向右移动。模式串与文本串口匹配时,模式串的整体挪动,是从左往右,但是,每次挪动后,从模式串的最后一个字符从右往左进行匹配。

实例 + 原理

下面我们来看一个实例:

加上匹配串和模式串如下:



首先从右向左进行匹配,c与c匹配成功,接着第二个字符b与a,匹配失败(失配位置为3)。

于是,从模式串当前位置往左寻找匹配失败的那个字符,也即在模式串中寻找字符b上一次出现的位置(注意这里的“上一次”是指在模式串中从当前失配位置往左找到的第一个与失配位置相同的字符);

结果我们在模式串中找到了字符b,其位置为1,那么就将模式串整体往右挪动,把刚才找到的字符b与之前与匹配串中失配的字符b对齐。总共移动了多少位呢?移动了(3-1)位。



模式串整体挪动到b处对齐后,再从右向左开始匹配,此时发现其第一个需要匹配的字符d与c就匹配失败(失配位置为4),尼玛,坑爹啊!那接下来怎么办?当然是跟上一步的方法一样,在模式串中去找失配的那个字符d,如果在模式串中找到了d,将模式串平移,使其d字符与匹配串的d对齐。结果发现模式串中根本就没有字符d。那接下来怎么办?直接将模式串平移到刚才失配字符d后面的。这是因为模式串中没有字符d,那么就不可能在匹配串中的d及其前面的字符中匹配成功。这一次我们移动的位数是4-(-1)=5位。



然后,又回到第1步的那种状态,从模式串的最后一个字符开始匹配,即c与c匹配,a与a匹配啊,然后发现b与c不匹配,从而我们在模式串中找b字符上一次出现的位置,发现其位置为1,移动模式串,将b字符与b字符对齐(如下图),这次我们移动的位数是2-1=1位。



终于,在经历第五步的那次挪动后,我们匹配成功了,是不是感觉匹配速度特别快?

有了以上实例,我们现在来抽取其一般规则,以方便编码实现:

我们得到的规则只有一条,即:

字符串后移位数=失配字符位置-失配字符上一次出现的位置


如果失配字符根本就没有出现在模式串中,我们将“失配字符上一次出现的位置”的值视为-1。

代码

# -*- coding: utf-8 -*-
"""
Created on Thu Jul 28 23:11:27 2016

@author: zang
"""

def Horspool(text, pattern):
t = len(text)
p = len(pattern)
cur = 0    #起始指针cur 表示 在text上开始匹配的起始位置
results = []  # 存储成功匹配的信息
flag = 0
mischar = ""
mispos = 0
while cur <= t - p:
for i in reversed(range(p)):
#print i,
if text[i+cur] != pattern[i]:
mischar = text[cur + i]
mispos = i
break
else:
flag += 1
#print flag
results.append(" "*cur + pattern + " "*(t - p - cur) + "  " + str(cur+1) + "  " + str(flag))
cur += 1
continue
for k in reversed(range(mispos - 1)):
if pattern[k] == mischar:
cur += (mispos - k)
break
if k == 0:
cur += mispos + 1
if flag == 0:
print "No find."
else:
print flag," matching results are listed below."
print "-------" + "-"*t + "-------"
print text
for line in results:
print line
print "-------" + "-"*t + "-------"

def main():
while 1:
text = raw_input("text: ")
pattern = raw_input("pattern: ")
if len(text) == 0 or len(pattern) == 0:
print "\nplease input text and pattern again!"
break
Horspool(text, pattern)

if __name__ == '__main__':
main()


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息