为什么这个用 Python 编写的 Rabin-Karp 代码这么慢?

问题描述

from time import process_time_ns
def initial_hash(desired):
    u=0
    for i in desired:
        u=(u*256+ord(i))%89
    return u
def find(Document):
    initial=Document[:len(desired)]
    hash_1=initial_hash(initial)
    for i in range(1,len(Document)-len(desired)+1):
        hash_1=skip(Document[i-1],hash_1)
        hash_1=append(Document[len(desired)+i-1],hash_1)
def append(char,u):
    u=(u*256+ord(char))%89
    return u
def skip(char,u):
    u=(u-(ord(char)*(constante)))%89
    return u
to=process_time_ns()
desired="ababa"
constante=(256**(len(desired)-1))%89
hash_desired=initial_hash(desired)
text=open("match.txt","r")
for x in text:
    find(x)
print(process_time_ns()-to)

我已经按照 MIT 课程 6006 实现了这段代码。我在上面的代码中使用了一些标记来查看时间。我将 match.txt 更改为许多不同的大小以及 desirable 变量,这是我想在文档中找到的变量。但是对于许多变体,链接中描述的朴素算法总是更快。我选择 89 作为质数。代码基于此链接

https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-algorithms-fall-2011/lecture-videos/MIT6_006F11_lec09_orig.pdf

解决方法

Rabin--Karp 比朴素算法具有更好的最坏情况渐近运行时间。这两个限定词都很重要:naive 具有线性时间最佳和平均情况,并且这个最佳情况下的常数比 Rabin--Karp 更好,因此在很多情况下它实际上会更快。如果您想看到很大的不同,请为天真选择错误的输入,例如在 aaaa(many repetitions of a)aaaab 中搜索 aaaa(many more repetitions of a)aaaab