私は最近、いくつかの助けを必要とするアルゴリズム設計の問題に遭遇しました:
たとえば、
a,e,o,g,z,k,l,j,w,n
と単語の辞書。ほとんどの文字を含む単語を辞書で見つけます。
辞書がツリーにあると仮定しましょう。与えられた文字の順列を見つけることから始めます。ここでは、再帰を使用できます。辞書の文字をチェックすることにより、再帰ツリーをプルーニングできます。そして、これまでに形成された最大の文字列を保持する変数を維持します。
このソリューションはどうですか?もっと良いものはありますか?
あなたができる最善のことは、比較の数を辞書の文字の数に減らすことです。
求めた:a、e、o、g、z、k、l、j、w、n
求められたキーの値が1であるアルファベットのインデックスを作成し、残りを0にします。
index={a:1, b:0, c:0, d:0, e:1, f:0, g:1...}
辞書の各単語を反復処理します。その単語の合計にインデックスの値を追加します。 Wordの位置と値が最高より大きい場合は、覚えておいてください。
max=0;
max_index=0;
foreach(dictionary as position=>Word)
{
sum=0;
foreach(Word as letter)
{
sum += index[letter];
}
if(sum > max)
{
max = sum;
max_index = position;
}
}
max_indexは、最大の文字数でWordを指します。一部の最適化では、現在の最大値より短い単語をスキップするか、単語の長さで並べ替えられた辞書から開始して、単語の長さが現在の最大値になったら停止します。
これは、リストの文字が何度でも繰り返されることを許可していることを前提としています。そうでない場合は、インデックスに特定のタイプの文字の数を含め、ゼロ以外のインデックス値が見つかるたびに合計を1増やし、インデックスを減らします。 (各行のインデックスをリセットします。)
今回は、前の最適化に加えて、max-sum未満の文字が残っている場合はWordのチェックを中止し、すべての文字を含むWordが見つかった場合は操作を中止します。
SFのソリューションに少し追加したいと思います。私の分析が正しいかどうかはわかりませんが、とにかく:
前処理が無料の場合(十分な回数の検索が行われることを考慮して)、ディクショナリ内の各単語を、前に述べたインデックスSFのようなエンティティを生成することによって前処理できます。したがって、各単語は次のような数字になります
01000100011101.... (up to the last letter a set of words can consist of)
ここで、各1は、Wordにこの文字があるかどうかを表します(簡略化するために、2文字以上ある場合は省略します)。
Wordが持つさまざまな文字の量によってこの変換されたディクテーションをさらに調整して、ほとんどの文字を含むものから検索を開始し、すでに一致している可能性のない範囲に入ると、検索を早期に中断することができます持ってる。
辞書の各単語(現在は数に削減されています)を反復処理するときは、単純にXORこの数と、探している文字のセットから生成された数を使用して、そのハミング重みを計算します(数of 1s)これは基本的にあなたが探しているものです。
https://en.wikipedia.org/wiki/Hamming_weight
入力のサイズは常に一定(可変のWordサイズではなくアルファベットのサイズ)であるため、一般に入手可能なアルゴで効率的に実行できます。これにより、文字を1つずつ比較する必要がなくなります。ダブル/トリプルレターの処理は、私が想定している構造を拡張することで実行できます。