指摘されているように、この問題はより一般的に知られている編集距離の問題(レーベンシュタイン距離の根底にある)に似ています。また、たとえば、動的タイムワーピング距離(最後の要件での複製、または「“音」)との共通点もあります。
動的プログラミングへのステップ
x=x1…xny=y1…ymd(x,y)
min⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪d(x,y1…ym−1)+1d(x,y2…ym)+1d(x,y1…ym/2)+1d(x1…xn/2,y)+1d(x1…xn,y)+1d(x1…xn−1,y1…ym−1)if y=y1…ym/2y1…ym/2if x=x1…xn/2x1…xn/2if yn=ym▻ Add letter at end▻ Add letter at beginning▻ Doubling▻ Halving▻ Deletion▻ Ignoring last elt.
ここで、最後のオプションは、基本的に、FOOXをBARXに変換することは、FOOをBARに変換することと同等であることを示しています。これは、「末尾に文字を追加」オプションを使用して、utter音(複製)効果とポイントでの削除を実現できることを意味します。問題は、それが自動的に追加できることです任意の文字列の途中で文字だけでなく、あなたはおそらくしたくない何かを。(この「同一の最後の要素を無視する」ことは、任意の位置で削除とutter音を達成する標準的な方法です。任意の挿入を禁止しますが、両端で追加を許可しますが、少し注意が必要です...)
他の誰かがそれを何らかの方法で「救助」できるように、また以下のヒューリスティックソリューションで使用するために、完全に仕事を果たさなくても、この内訳を含めました。
(もちろん、実際に距離を定義するこのような内訳を取得できる場合、メモを追加するだけで解決策が得られます。ただし、プレフィックスを操作しているだけではないため、メモ化にインデックスだけを使用できるとは思わない。実際の変更された文字列を呼び出しごとに保存する必要があるかもしれませんが、文字列がかなりのサイズである場合は巨大になります)
発見的解決へのステップ
別のアプローチは、理解しやすく、スペースをかなり少なくすることができますが、アルゴリズムを使用して、最初の文字列から2番目の文字列までの最短「編集パス」を検索することです(基本的に、最初の分岐限定)。サーチスペースは、編集操作によって直接定義されます。さて、大きな文字列の場合、次のようになりますA∗A ∗任意のキャラクターを削除するか(削除の可能性ごとに隣人を与える)、任意のキャラクターを複製する(再び、隣人の線形数を与える)だけでなく、両端に任意の文字を追加できるため、アルファベットサイズの2倍の数の隣人を指定します。(完全なUnicodeを使用していないことを願っています;-)このような大規模なファンアウトでは、双方向 またはいくつかの相対A∗を使用して、大幅な高速化を達成できます。
機能させるには、ターゲットまでの残りの距離の下限が必要です。ここに明確な選択肢があるかどうかはわかりませんが、あなたができることは、上記で示した再帰的分解に基づいて動的プログラミングソリューションを実装することです(文字列が非常に長い場合は、スペースの問題が発生する可能性があります)。この分解は距離を正確に計算するわけではありませんが、下限が保証されています(より許容度が高いため)。つまり、ヒューリスティックとして機能します。(どれだけタイトかはわかりませんが、正しいでしょう。)もちろん、バインドされた関数のメモ化は、中のバインドのすべての計算で共有できますA ∗ A ∗A∗A∗A∗走る。(時間/スペースのトレードオフがあります。)
そう…
私が提案したソリューションの効率は、(1)文字列の長さと(2)アルファベットのサイズにかなり依存しているように思われます。どちらも巨大ではない場合、動作する可能性があります。あれは:
- 私の再帰分解と動的プログラミングを使用して(たとえば、メモされた再帰関数を使用して)、距離の下限を実装します。
- 状態空間での「移動」としての編集操作と、動的プログラミングベースの下限を使用して、(または双方向)を実装します。A ∗A∗A∗
私はそれがどれほど効率的であるかについての保証を本当にすることはできませんが、それは正しいはずです、そしてそれはおそらくブルートフォースのソリューションよりもずっと良いでしょう。
他に何もなければ、これがあなたにさらなる調査のためのいくつかのアイデアを与えることを望みます。