すべての可能な解決策が必要ではなく、「受け入れリスト」の少なくとも 1 つの項目に一致し、「無視リスト」の項目に一致しないマスクのリストのみが必要な場合は、次の方法で現在のアルゴリズムを改善できる可能性が高くなります。単純なO(n*m)
アルゴリズムを作成します (ここでn
、 とm
はリストの長さです)。
リストが比較的短い場合、これは 0 から 2 29まで反復するよりもはるかに高速に機能します。さらに、これらのリストが変更されることがなく、これを 1 回だけ行う必要がある場合は、おそらくこれが最適な選択です。
疑似アルゴリズムは次のようになります。
for each candidate in the "accept list"
do a bitwise AND with all items in the "ignore list"
if there is a match then (break as soon as you find a match)
this candidate cannot be matched
else
this candidate is one of the solutions
もちろん、これは単一のアイテムのみに一致するマスクを返します。マスクの最小セットが必要な場合は、候補リストを後処理し、他のマスクに既に含まれているマスクを破棄できます (これは追加O(n*n)
です)。
「無視リスト」に多数のアイテムがあり、リストを頻繁に検索する必要がある場合は、無視されたアイテムをトライ(または基数トライ、またはDAWG、これらはより多くまたは少ない同じもの)。
候補ごとに、トライを少しずつ調べて、マスク1
のビットの代わりにビットがあるアイテムをすばやく破棄します。0
これはO(n+m)
複雑さのようなものを与えます(O(m)
トライを構築O(1*n)
し、受け入れリストの各アイテムのトライを検索します):
(presuming you have built a trie from "ignore list" items)
for each candidate in the "accept list"
get a binary representation of the candidate
perform a dfs of the trie
if node at level k is 1 and candidate bit at position k is 0
then
discard that subtree
else
continue searching until the last leaf
これはすべて、リストの実際の長さと、この検索を実行する必要がある頻度によって異なります。それぞれ 10000 項目の 2 つのリストがあり、これを 1 回だけ実行する必要がある場合、最初のアルゴリズムを選択します。終了までにおそらく数秒しかかかりません (正確な実行時間は、無視リストの初期の一致)。