KMP算法是一个里程碑式的算法。它的出现宣告人类找到了一种具有线性时间复杂度的字符串匹配算法。之后出现了很多字符串匹配算法,如BM算法、Sunday算法等。
这些算法在时间复杂度上都达到了线性时间。但实际应用中所花费的时间还是有差异的。
BM算法在实际应用中的效率已经达到KMP算法的四五倍。
Sunday算法的效率甚至比BM算法还要高。
了解这两种算法的学生将会理解:
Sunday算法确实比BM算法更容易理解。
正文
好了,赞美周日算法就到此为止,言归正传吧!
PS:下面将匹配字符串称为文本字符串,将匹配字符串称为模式字符串。
为什么周日算法这么容易理解?
因为它只比暴力匹配算法多了一步!
废话不多说,直接上我精心制作的GIF动画:
可以看到,我们只移动了3次,就直接找到了最终的结果。
Sunday算法是从前到后的匹配算法(BM算法是从后到前)。当匹配失败时,焦点位于参与匹配的文本字符串中最后一个字符的下一个字符。
如果该字符没有出现在模式串中,则直接跳过,即移位位数=模式串长度+1。否则,移位位数=模式串长度-最右边位置字符(从0开始)=模式串中字符最右边位置到尾部的距离+1。Sunday算法最巧妙的地方在于,它发现匹配失败后,可以直接检查下一个字符参与匹配的文本字符串中最后一个字符的位置。
在Python代码中,我们使用字典来存储模式字符串中每个字符最后一次出现的索引。这样前期只需要O(M),M为模式串的长度即可完成前期准备,然后进行查询。这是O(1) 时间。
同时,为了防止越界,我在下面贴出的python代码中手动在字符串末尾添加了一个’\0’字符。
代码
class Sunday(object): def __init__(self, pattern:str): # 模式字符串及其长度self.pattern, self.length=pattern, len(pattern) # 基于模式字符串构建的偏移字典self.shift_dict={ } # 为索引构建字典,值在enumerate(pattern): self.shift_dict[value]=self.length – 索引def match(self, text:str): i=0 text_length=len(text) text +=’\0 ‘ while i=text_length – self.length: j=0 while self.pattern[j]==text[i + j]: j +=1 if j=self.length: return i offset=self.shift_dict[text[i+ self. length]] if text[i+self.length] in self.shift_dict else self.length + 1 i +=offset return -1s=Sunday(‘nihao’)print(s.match(‘dasoijfoasjdoifjasdoifjoinihao’)) 代码它是很简单。同时,我构建了一个类,以在同一模式字符串下重用其位置字典并简化代码。
Sunday算法与KMP算法大比拼
写完代码后,我对KMP算法和Sunday算法的匹配时间进行了粗略的测试。测试结果如下:
太神奇了!Sunday算法的平均匹配速度大约是KMP算法的七倍!
KMP和Sunday分别构造一个对象,然后每次生成一个长度为10万个字符的随机字符串,开始匹配。
生成-匹配这个过程循环一百次,最后计算出平均时间。如果有人觉得不放心,我会在下面放出检测代码。您可以自己修改测试并立即使用!
检测代码如下
类KMP(): def __init__(self, ss: str) – list: self.length=len(ss) self.next_lst=[0 for _ in range(self.length)] self.next_lst[0]=- 1 i=0 j=-1 while i self.length – 1: 如果j==-1 或ss[i]==ss[j]: i +=1 j +=1 如果ss[i]==ss[ j]: self.next_lst[i]=self.next_lst[j] else: self.next_lst[i]=j else: j=self.next_lst[j] self.pattern=ss def match(self, ss:str): ans_lst=[ ] j=0 for i in range(len(ss)): if ss[i] !=self.pattern[j]: j=self.next_lst[j] if self.next_lst[j] !=-1 else 0 if ss[i]==self.pattern[j]: j +=1 if j==self.length: return i + 1 – self.length return -1class Sunday(object): def __init__(self,pattern:str): #模式字符串及其长度self.pattern, self.length=pattern, len(pattern) # 基于模式字符串构建的偏移字典self.shift_dict={} # 为索引构建字典,值在enumerate(pattern): self.shift_dict [ value]=self.length – 索引def match(self, text:str): i=0 text_length=len(text) text +=’\0′ while i=text_length – self.length: j=0 while self.pattern[j ]==text[i + j]: j +=1 if j=self.length: return i offset=self.shift_dict[text[i+self.length]] if text[i+self.length] in self.shift_dict else self.length + 1 i +=offset return -1import randomimport timesunday=Sunday(‘helloworld’)kmp=KMP(‘helloworld’)kmp_average_time=0sunday_average_time=0for i in range(100): ss=”.join([ chr (random.randint(97, 122)) for _ in range(100000)]) st=time.process_time() sunday.match(ss) ed=time.process_time() sunday_average_time +=ed – st st=时间。 process_time() kmp.match(ss) ed=time.process_time() kmp_average_time +=ed – stprint(‘kmp 平均时间: {}’.format(kmp_average_time/100))print(‘周日平均时间: {}’. format(sunday_average_time/100))
最后
最后,如果您觉得这篇文章对您有帮助,请关注并保存!
用户评论
苏樱凉
哇,这个动画演示真是太清晰了!Sunday算法比KMP算法快七倍,这太神奇了,我得好好研究一下。
有13位网友表示赞同!
我家的爱豆是怪比i
看了这个动画,我才发现Sunday算法这么强大,果然算法的世界博大精深。
有20位网友表示赞同!
不离我
周日算法比KMP快七倍,这让我对算法有了新的认识,太有用了!
有15位网友表示赞同!
汐颜兮梦ヘ
这个Sunday算法演示太棒了,让我对字符串匹配有了新的理解,谢谢分享!
有8位网友表示赞同!
非想
原来Sunday算法这么高效,怪不得有人说它比KMP快七倍,学到了新知识。
有11位网友表示赞同!
情如薄纱
看了这个动画,我对Sunday算法有了更深的理解,感觉比KMP算法更简单易懂。
有18位网友表示赞同!
心安i
Sunday算法比KMP算法快七倍,这让我对算法的优化有了新的认识,太惊喜了!
有12位网友表示赞同!
忘故
这个动画演示做得很好,让我对Sunday算法有了直观的认识,真的学到了不少。
有11位网友表示赞同!
凉话刺骨
Sunday算法比KMP算法快七倍,这让我对算法的选择有了新的思考,感谢分享!
有7位网友表示赞同!
冷嘲热讽i
看了这个Sunday算法的动画演示,我对字符串匹配有了全新的认识,太有帮助了。
有7位网友表示赞同!
一样剩余
Sunday算法这么厉害,比KMP快七倍,我得好好研究一下,提升自己的编程能力。
有18位网友表示赞同!
半梦半醒半疯癫
这个动画演示让我对Sunday算法有了更深的了解,感觉算法的优化真的很重要。
有8位网友表示赞同!
有你,很幸福
周日算法的动画演示做得太好了,让我对算法有了更直观的感受,点赞!
有6位网友表示赞同!
哭花了素颜
Sunday算法比KMP快七倍,这让我对算法的效率有了新的认识,太震撼了!
有8位网友表示赞同!
花容月貌
看了这个Sunday算法的动画演示,我对算法的选择有了新的思考,谢谢分享!
有20位网友表示赞同!
像从了良
Sunday算法这么高效,我得好好研究一下,希望能应用到实际项目中。
有16位网友表示赞同!
?亡梦爱人
这个动画演示让我对Sunday算法有了更深的理解,感觉算法的优化真的很重要。
有15位网友表示赞同!
沐晴つ
周日算法比KMP快七倍,这让我对算法的原理有了新的认识,太有用了!
有8位网友表示赞同!
寻鱼水之欢
这个Sunday算法的动画演示让我对字符串匹配有了全新的认识,太有帮助了。
有15位网友表示赞同!
ー半忧伤
看了这个动画,我对Sunday算法有了更深的理解,感觉算法的世界真的太奇妙了。
有18位网友表示赞同!