私は運動末尾再帰レーベンシュタイン距離
let lastchar (s:string) = s.Substring(s.Length-1, 1)
let lastchar_substring (s:string) len = s.Substring(len-1, 1)
let rec levdist (sa:string) (sb:string) alen blen = match alen, blen with
| -1, -1 -> levdist sa sb sa.Length sb.Length
| 0, 0 -> 0
| _ , 0 -> alen
| 0, _ -> blen
| _ -> List.min [ (* How do I make this tail recursive...? *)
(levdist sa sb (alen-1) blen) + 1;
(levdist sa sb alen (blen-1)) + 1;
(levdist sa sb (alen-1) (blen-1)) +
match (lastchar_substring sa alen), (lastchar_substring sb blen) with
| x, y when x = y -> 0
| _ -> 1
])
としてF#でかなり標準的な方法でレーベンシュタイン距離を実現ししかし、私は末尾再帰するList.minコールを変換する簡単な方法が表示されません。再帰呼び出しの後に、単に独立した計算を追加するだけではありません。代わりに、複数の再帰呼び出しの結果を選択しています。
エレガントにこれを尾を再帰的に変換する方法はありますか?
(私は簡単に+1
は末尾再帰であることを変換することができます)
Iを私は解決策を見ていると思う...しかし、それは超畳み込まれているようです。 levdistを3回呼び出してからminを取る代わりに、levdist(alen-1 blen)と呼んでlevdist(alen blen-1)と呼ぶいくつかの連続を渡すことができます。 min opは連続で行われます。 – jameszhao00
私はそれが尾を再帰的にすることについてあまり心配しないでしょう - あなたのアルゴリズムは指数関数的な作業を必要とするように見えるので、スタックをあふれさせる危険はありません。 – kvb
ちょうど練習として:)この(非末尾再帰的な)関数をn * m(n^2 ish)とメモすることができます。 – jameszhao00