algorithm - 作业 : Implementing Karp-Rabin; For the hash values modulo q, 解释为什么用 q 作为 2 的幂是个坏主意?

标签 algorithm hash bioinformatics biopython rabin-karp

我有一个双重作业问题,实现 Karp-Rabin 并在测试文件上运行它,第二部分:

  1. For the hash values modulo q, explain why it is a bad idea to use q as a power of 2. Can you construct a terrible example e.g. for q=64 and 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 的基因组)上运行该算法并且没有明显的区别。

我试着查看如何推导哈希值的公式(我不擅长数学),试图找到一些对 2 的幂非常不利的公因数,但一无所获。我觉得如果 q 是 2 的幂,它应该会导致很多哈希冲突,因此您需要更多地比较字符串,但我也没有发现任何类似的东西。

我真的很感激这方面的帮助,因为我很困惑。如果有人想指出我在第一部分中可以做得更好的地方(代码效率、可读性、正确性等),我也很高兴听到您对此的意见。

最佳答案

如果 q 除以 d 的某个次方,就会出现问题,因为这样只有少数字符对散列有贡献。例如,在您的代码 d=4 中,如果您采用 q=64,则只有最后三个字符确定哈希值 (d**3 = 64)。

如果 q 是 2 的幂但 gcd(d,q) = 1,我真的看不出问题。

你的实现看起来有点奇怪,因为不是

if pattern_hash % q == text_hash % q and pattern == text[i:i+n]:

你也可以用

if pattern_hash == text_hash and pattern == text[i:i+n]:

这会更好,因为碰撞更少。

关于algorithm - 作业 : Implementing Karp-Rabin; For the hash values modulo q, 解释为什么用 q 作为 2 的幂是个坏主意?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32441619/

相关文章:

c# - 使用 rand.Next() 重复结果的概率

perl - 在 perl 中对哈希键进行排序,键是制表符分隔的

python - 散列嵌套元组的限制?

php - MySQL SHA() 不起作用

r - 如何根据 R 中定义的列中缺失值的数量返回行值的总和?

java - 在另一个字符串中查找字符串的 Anagrams 的最佳算法

algorithm - 素因数计算的费马算法

python-2.7 - 使用 Biopython 基于 IDS 过滤 FASTA 文件

python - 在 matplotlib 中绘制 Needleman-Wunsch 成对序列比对的得分矩阵

groovy - 用于处理给定目录中所有文件的 Nextflow 脚本