のサブセットのコレクションを表し、次の操作をサポートするためにどのデータ構造を推奨しますか?
- S:コレクションにを挿入します。
- S ' S ' ⊂ S:になるようなコレクションにが存在する場合はtrueを返し、それ以外の場合はfalseを返します。
私の主な基準は、実用的な時間効率です。
のサブセットのコレクションを表し、次の操作をサポートするためにどのデータ構造を推奨しますか?
私の主な基準は、実用的な時間効率です。
回答:
あなたの問題は、情報検索(IR)によく似ています。そこには単語のセット(ドキュメントとも呼ばれます)のコレクションがあり、存在だけでなく、クエリ条件を満たすすべてのセット/ドキュメントを検索したいとします。
セットの要素は数値なので、見かけ上の構造を利用できるため、シグネチャインデックスは非常に役立ちます。
特に木のような辞書の構造に関連するIRペーパーを確認することをお勧めしますが、スペースは通常これらのシステムでは問題ですが、ケースでは問題にならない場合があります。
検索ツリーを使用できます。順序付けされたユニバース(実数、文字列…)に使用されるような「標準」タイプではなく、GiSTプロジェクトによってほのめかされたタイプなど、より一般的なタイプ。空間クエリ用の検索ツリーと、メトリック(距離)空間にインデックスを付けるためのメトリック公理に基づく検索ツリーがあります。一般的な考え方(通常の順序付けされた検索ツリーの「より小/より大」の間隔指向のアプローチは特殊化されています)は、データセットを通常は階層的にサブセットに分解することです。このサブセットの階層は(明らかに)ツリーで表され、各ノードの子はサブセットを表し、各ノードには何らかの形の述語があります。を使用すると、クエリに関連する(概念的な)オブジェクトのセットと、そのサブツリー(サブセット)にあるオブジェクトの間にオーバーラップがあるかどうかを確認できます。
たとえば、ユークリッド平面の空間ツリーの場合、各オブジェクトはポイントであり、述語は境界矩形であり、そのノード内またはその下にあるすべてのポイントを含みます。クエリが四角形である場合(およびその四角形内のすべてのポイントを検索する場合)、境界の四角形がクエリと重複しないサブツリーを再帰的に削除できます。
あなたのケースでは、各ノードがクエリがサブセットであるかどうかを検出できるいくつかのセット構造を含むツリーを構築できます。そうでない場合は、クエリが子ノードのサブセットになることは決してない(そして、おそらく本当のデータを表す葉ではない)ため、サブツリー全体を削除できます。
通常の検索ツリーとは異なり、ここでは一般的に検索時間の保証はありません。おそらく複数のブランチにアクセスするため、完全にバランスの取れたツリーがあっても、おそらく超対数の実行時間になります。これはヒューリスティックなアプローチですが、それでも効果的です。
このツリーを構築するために必要なのは、データに適合する何らかの形の階層的クラスタリング手法です。GiSTプロジェクトは実際には、C実装を使用して、必要なものと非常によく似たツリーを持っています(ただし、サブセットであるかどうかではなく、クエリがオーバーラップするかどうかをチェックします。簡単に変更できるはずです)。ただし、GiSTのディスクベースのBツリースタイルのバランスツリーはやり過ぎかもしれません。おそらく、類似のセットを階層的に一緒にクラスタ化したいだけで、既成のクラスタリングアルゴリズムを使用して、ハミング距離(またはより凝ったもの)のようなものを使用してそれを行うことができます。兄弟ノードが類似しているほど、親の境界述語(つまり、それらの和集合を表すセット)が「よりタイト」になります。したがって、検索がより効率的になります。
要約すると、私の提案は:
ツリーを動的にする必要がある場合、それを行う方法もたくさんあります。たとえば、ツリーを再帰的にトラバースし、(オーバーラップが最も大きい/ハミング距離が最も小さいノードを通過することにより)最適な場所を見つけ、移動しながらユニオン(境界述語)を更新できます。削除は、おそらくもう少しトリッキーです。オブジェクトを欠落としてマークし、マークされたオブジェクトの数が特定のしきい値に達したときにサブツリー(または構造全体)を再構築することができます。
これがアプリケーションにうまく機能するかどうかは、アプリオリに言うのは難しいかもしれませんが、実験的に確認するのは簡単です。また、微調整の余地がたくさんあります。