PythonでLevenshtein距離を計算するプログラムを作成しています。私はアルゴリズムを再帰的に実行しているのでメモを実装しました。私の元の機能は、機能自体にメモを実装しました。以下はその外観です:最大再帰深度を超えましたが、デコレータを使用した場合のみ
# Memoization table mapping from a tuple of two strings to their Levenshtein distance
dp = {}
# Levenshtein distance algorithm
def lev(s, t):
# If the strings are 0, return length of other
if not s:
return len(t)
if not t:
return len(s)
# If the last two characters are the same, no cost. Otherwise, cost of 1
if s[-1] is t[-1]:
cost = 0
else:
cost = 1
# Save in dictionary if never calculated before
if not (s[:-1], t) in dp:
dp[(s[:-1], t)] = lev(s[:-1], t)
if not (s, t[:-1]) in dp:
dp[(s, t[:-1])] = lev(s, t[:-1])
if not (s[:-1], t[:-1]) in dp:
dp[(s[:-1], t[:-1])] = lev(s[:-1], t[:-1])
# Returns minimum chars to delete from s, t, and both
return min(dp[(s[:-1], t)] + 1,
dp[(s, t[:-1])] + 1,
dp[(s[:-1], t[:-1])] + cost)
これは機能します。しかし、私はusing decoratorsをメモする方法を見つけました。私はアルゴリズムにこの手法を適用しようとしました:
# Memoization table mapping from a tuple of two strings to their Levenshtein distance
def memoize(func):
memo = {}
def wrap(s, t):
if (s, t) not in memo:
memo[(s, t)] = func(s, t)
return memo[(s, t)]
return wrap
# Levenshtein distance algorithm
@memoize # lev = memoize(lev)
def lev(s, t):
# If the strings are 0, return length of other
if not s:
return len(t)
if not t:
return len(s)
# If the last two characters are the same, no cost. Otherwise, cost of 1
if s[-1] is t[-1]:
cost = 0
else:
cost = 1
# Returns minimum chars to delete from s, t, and both
return min(lev(s[:-1], t) + 1,
lev(s, t[:-1]) + 1,
lev(s[:-1], t[:-1]) + cost)
私には、これはよりクリーンで混乱が少ないようです。私は2つが機能的に同等であると思ったが、デコレータを使ってバージョンを実行したとき、私はRecursionError: maximum recursion depth exceeded
を得たことに驚いた。
正確に何が欠けていますか?デコレータを機能的に同等のものに使用していませんか?私はsys.setrecursionlimit(1500)
を追加して修正を試みましたが、これはうまくいきますが、それはハックであり、2つの機能が異なっている理由を説明していません。
注:私はウィキペディアからsとtのための私のテスト文字列としてLoremのイプサムの1つの段落を使用しています:
Loremのイプサム嘆きをAMET座る、consectetur adipiscing ELIT、eiusmod temporんsedのincididunt UT laboreらdolore magna aliqua。最小限に抑えて、練習や練習をすることができます。大気中に放出された栄養素は、栄養補助食品中に存在する。例外的な兆候を見せている人は、善意ではないと主張しています。
さらに長い文字列の場合、私の最初の機能は失敗することを理解しています。私はちょうど装飾されたものが最初に失敗する理由を知りたい。ありがとう!
あなたのコードは 'cost = 1 - (s [-1]はt [-1])'でクリーンアップできます –