我有一个双重作业问题,实施 Karp-Rabin 并在测试文件和第二部分上运行它:
- 对于以 q 为模的哈希值,解释为什么使用 q 作为 2 的幂是一个坏主意。你能构造一个糟糕的例子,例如 q=64 和 n=15 吗?
这是我的算法实现:
def karp_rabin(text, pattern):
# setup
alphabet = 'ACGT'
d = len(alphabet)
n = len(pattern)
d_n = d**n
q = 2**32-1
m = {char:i for i,char in enumerate(alphabet)}
positions = []
def kr_hash(s):
return sum(d**(n-i-1) * m[s[i]] for i in range(n))
def update_hash():
return d*text_hash + m[text[i+n-1]] - d_n * m[text[i-1]]
pattern_hash = kr_hash(pattern)
for i in range(0, len(text) - n + 1):
text_hash = update_hash() if i else kr_hash(text[i:n])
if pattern_hash % q == text_hash % q and pattern == text[i:i+n]:
positions.append(i)
return ' '.join(map(str, positions))
...问题的第二部分是指代码/算法的这一部分:
pattern_hash = kr_hash(pattern)
for i in range(0, len(text) - n + 1):
text_hash = update_hash() if i else kr_hash(text[i:n])
# the modulo q used to check if the hashes are congruent
if pattern_hash % q == text_hash % q and pattern == text[i:i+n]:
positions.append(i)
我不明白为什么使用 q 作为 2 的幂是个坏主意。我已经尝试在提供的测试文件(这是 ecoli 的基因组)上运行算法并且没有明显的区别。
我尝试查看如何导出哈希的公式(我不擅长数学),试图找到一些对二次幂非常不利的共同因素,但一无所获。我觉得如果 q 是 2 的幂,它应该会导致很多哈希冲突,所以你需要更多地比较字符串,但我也没有找到任何类似的东西。
我真的很感激这方面的帮助,因为我很难过。如果有人想指出我在第一部分可以做得更好(代码效率、可读性、正确性等),我也很高兴听到您对此的意见。