リンクした種類のアナグラム ソルバーを作成する目的で、要求しているアルゴリズムは必要ありません。また、非常に高価です。
MONKEY
たとえば、 のような 6 文字の単語を見てみましょう。単語の 6 文字すべてが異なるため、次のように作成します。
- 6*5*4*3*2*1 異なる 6 文字の単語
- 6*5*4*3*2 の異なる 5 文字の単語
- 6*5*4*3 の異なる 4 文字の単語
- 6*5*4 の異なる 3 文字の単語
- 6*5 の異なる 2 文字の単語
- 合計1950ワード
おそらく、あなたは 1950 語すべて (例えば 'OEYKMN') をアナグラムとして吐き出そうとしているわけではありません (それらはそうですが、それらのほとんどは意味不明でもあります)。あなたは合法的な英語の単語の辞書を持っていると思います。これらの単語のいずれかがクエリ単語のアナグラムであるかどうかを確認したいだけで、すべての文字を使用しないというオプションがあります。
その場合、問題は単純です。
2 つの単語が互いにアナグラムであるかどうかを判断するには、それぞれの文字が何回使われているかを数え、これらの数字を比較するだけです。
大文字と小文字を区別せずに、26 文字の AZ のみに制限しましょう。必要なcountLetters
ことは、単語を受け取り、26 個の数値の配列を返す関数を作成することです。配列の最初の数値はA
単語内の文字の数に対応し、2 番目の数値は の数に対応しますB
。
次に、2 つの単語W1
andは、 for every !のW2
場合、正確なアナグラムです。つまり、各単語は各文字をまったく同じ回数使用しています。countLetters(W1)[i] == countLetters(W2)[i]
i
MONEY
サブアナグラム (は のサブアナグラムMONKEY
)と呼ぶものは、 if for every !W1
のサブアナグラムです。つまり、サブアナグラムは特定の文字を使用することはできますが、使用する文字を増やすことはできません!W2
countLetters(W1)[i] <= countLetters(W2)[i]
i
(注:MONKEY
は のサブアナグラムでもありMONKEY
ます)。
これにより、十分に高速なアルゴリズムが得られます。クエリ文字列が与えられた場合、辞書を 1 回読み込んで、各単語の文字カウント配列をクエリ単語の文字カウント配列と比較するだけです。いくつかの小さな最適化を行うことができますが、これで十分です。
または、最高のパフォーマンスが必要な場合は、辞書 (事前にわかっている) を前処理して、サブアナグラム関係の有向非巡回グラフを作成できます。
説明のために、このようなグラフの一部を次に示します。
D=1,G=1,O=1 ----------> D=1,O=1
{dog,god} \ {do,od}
\
\-------> G=1,O=1
{go}
基本的に、各ノードは、同じ文字カウント配列を持つすべての単語のバケットです (つまり、それらは正確なアナグラムです)。次に、ノード fromN1
からN2
ifN2
の配列が<=
(上で定義されているように)N1
の配列です (推移的な削減を実行して、最小量のエッジを保存できます)。
次に、単語のすべてのサブアナグラムを一覧表示するには、その文字カウント配列に対応するノードを見つけ、そのノードから到達可能なすべてのノードを再帰的に探索するだけです。すべてのバケットにサブアナグラムが含まれます。