Karp-Rabin を実装し、テスト ファイルと 2 番目の部分で実行するという 2 つの宿題の問題があります。
- 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))
...質問の2番目の部分は、コード/アルゴリズムのこの部分を参照しています:
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 の累乗である場合、ハッシュに対して多くの衝突が発生するはずなので、文字列をさらに比較する必要があるように感じますが、それらの線に沿って何も見つかりませんでした。
私は困惑しているので、これについて助けていただければ幸いです。最初の部分で改善できる点 (コードの効率、読みやすさ、正確さなど) を誰かが指摘したい場合は、それについての意見もお待ちしています。