次の操作を効率的にサポートするデータ構造はありますか?
- セットを追加
- セットのサブセットが追加されたかどうかを照会します。
これは、すべてのクエリ中にすべての追加セットをテストすることにより、線形オーバーヘッドで実装できます。より効率的に実装できますか?偽陽性/陰性の小さな確率は許容されます(ブルームフィルタースタイルなど)。
次の操作を効率的にサポートするデータ構造はありますか?
これは、すべてのクエリ中にすべての追加セットをテストすることにより、線形オーバーヘッドで実装できます。より効率的に実装できますか?偽陽性/陰性の小さな確率は許容されます(ブルームフィルタースタイルなど)。
回答:
あなたのすべてのセットが有限のサブセットであるとしましょう 。しましょう セットのセットを示します。
次の2つの操作が必要です。
:すべての 、 追加 に
:すべての 、いくつかありますか そのため ?
スピードアップするためのアイデアをいくつか紹介します。
セットが別のサブセットであるかどうかをテストするので、おそらくサイズを維持する必要があります 各セットの で利用可能 テストする必要があるときに 、まず、 そうでない場合は、すぐにfalseを返すことができます。そして、あなたは確かに持っています、その後、通常の低速テストを実行します。
あなたが持っている場合は注意してください そして 、 そのため 、その後 、あなたも持っています 。だからあなたは保つ必要はありません に ために 。だからあなたは表すことができます セットのセットによって そして 意味する 。言い換えれば、あなただけのセットを追跡する必要があります含めるのは最小限です。これはかなり効率的に実装できます:セットを追加するとき、すべてのセット そのため (枢機卿の昇順で並べ替え) 、次に追加しないでください 最小限ではない(またはすでに存在するため) )。それ以外の場合は、 そしてセットの間で そのため 、それらを削除して、 (それらはもはや最小ではないため)。
セットを保つ それはすべてのセットの和集合に等しい 。次に、実行する代わりに、実行できます 代わりに(一部の場合 、 、それ以来 、 で、もし 、その後 )。
これらのアイデアを念頭に置いて、私は代表します 辞書(ペアの二重リンクリストとして実装) キーの昇順で) そのため に含まれる最小限の(含まれる)セットを正確に含む二重リンクリストです 枢機卿の 。
O1(S,s')
if O2(S,s')
return
if d(k) doesn't exist
d(k) := new_doubly_linked_list()
add(d(k),s')
S.t := union(S.t, s')
for each key k of d so that |s'|+1 <= k
for s in d(k)
if subset(s', s)
remove s
_O2(S,s')
for each key k of d so that k <= |s'|
for s in d(k)
if subset(s,s')
return true
return false
O2(S,s')
return _O2(S,inter(S.t,s'))
(私がのコードで明示的にそれをしなかったとしても、をO1
表す二重にリンクされたリストの単一のトラバーサルを行うことができることに注意してくださいd
)
最悪の場合、あまり改善しないと思いますが、平均的には改善するはずです。