セットのコレクションからセットのサブセットを見つける


8

のサブセットのコレクションを表し、次の操作をサポートするためにどのデータ構造を推奨しますか?{1,,n}

  • Sinsert(S):コレクションにを挿入します。S
  • S ' S 'Squery(S):になるようなコレクションにが存在する場合はtrueを返し、それ以外の場合はfalseを返します。SSS

私の主な基準は、実用的な時間効率です。


3
推奨には基準が必要です。あなたの基準は何ですか?たとえば、シンプルさ、空間、または時間?あなたがより具体的であるほど、あなたに役立つ答えを得る可能性が高くなります。
伊藤剛

あなたが正しい、それを指摘してくれてありがとう 私の主な基準は、実用的な時間効率です。
Caleb Poucher 2011

1
実行するクエリの数に対して、実行する挿入の数を知っていますか?時間でセットを照会できるようにする巨大なデータ構造(サイズは指数関数)を構築することが可能です。一方、が挿入されたサブセットの総数である場合、時間で追加のストレージなしで単純な検索を実行できます。その間のすべてがトレードオフになると思います。S O n m O n m nSO(n)mO(nm)
ジェームズキング

クエリの数は、挿入の数よりもはるかに多くなります(おそらく倍)。セットをポイントとして表現し、範囲ツリーを使用することを検討しましたが、これは指数関数的なサイズにもつながります。挿入のはの指数係数を、クエリの場合はの線形係数を回避する方法はあるのでしょうか。{ 0 1 } N、N 、N 、M100{0,1}nnnm
Caleb Poucher

とが何であるかについての大まかな考えはありますか?mnm
ジェームズキング

回答:


1

あなたの問題は、情報検索(IR)によく似ています。そこには単語のセット(ドキュメントとも呼ばれます)のコレクションがあり、存在だけでなく、クエリ条件を満たすすべてのセット/ドキュメントを検索したいとします。

セットの要素は数値なので、見かけ上の構造を利用できるため、シグネチャインデックスは非常に役立ちます。

特に木のような辞書の構造に関連するIRペーパーを確認することをお勧めしますが、スペースは通常これらのシステムでは問題ですが、ケースでは問題にならない場合があります。


良い点は、これは確かにドキュメント内の用語の検索と非常によく似ており、最も一般的な解決方法は、本の索引のように機能するいわゆる逆ファイルを使用することです。クエリの各用語を転置ファイルで検索し、その用語を含むドキュメントのリスト/セットを取得します。次に、これらのリストを交差させて結果を取得します。(たとえば、ハッシュテーブルを使用して、アイテムIDをセットIDの並べ替えられたリストにマッピングできます。並べ替えは、交差に役立ちます。)
Magnus Lie Hetland '27

0

検索ツリーを使用できます。順序付けされたユニバース(実数、文字列…)に使用されるような「標準」タイプではなく、GiSTプロジェクトによってほのめかされたタイプなど、より一般的なタイプ。空間クエリ用の検索ツリーと、メトリック(距離)空間にインデックスを付けるためのメトリック公理に基づく検索ツリーがあります。一般的な考え方(通常の順序付けされた検索ツリーの「より小/より大」の間隔指向のアプローチは特殊化されています)は、データセットを通常は階層的にサブセットに分解することです。このサブセットの階層は(明らかに)ツリーで表され、各ノードの子はサブセットを表し、各ノードには何らかの形の述語があります。を使用すると、クエリに関連する(概念的な)オブジェクトのセットと、そのサブツリー(サブセット)にあるオブジェクトの間にオーバーラップがあるかどうかを確認できます。

たとえば、ユークリッド平面の空間ツリーの場合、各オブジェクトはポイントであり、述語は境界矩形であり、そのノード内またはその下にあるすべてのポイントを含みます。クエリが四角形である場合(およびその四角形内のすべてのポイントを検索する場合)、境界の四角形がクエリと重複しないサブツリーを再帰的に削除できます。

あなたのケースでは、各ノードがクエリがサブセットであるかどうかを検出できるいくつかのセット構造を含むツリーを構築できます。そうでない場合は、クエリが子ノードのサブセットになることは決してない(そして、おそらく本当のデータを表す葉ではない)ため、サブツリー全体を削除できます。

通常の検索ツリーとは異なり、ここでは一般的に検索時間の保証はありません。おそらく複数のブランチにアクセスするため、完全にバランスの取れたツリーがあっても、おそらく超対数の実行時間になります。これはヒューリスティックなアプローチですが、それでも効果的です。

このツリーを構築するために必要なのは、データに適合する何らかの形の階層的クラスタリング手法です。GiSTプロジェクトは実際には、C実装を使用して、必要なものと非常によく似たツリーを持っています(ただし、サブセットであるかどうかではなく、クエリがオーバーラップするかどうかをチェックします。簡単に変更できるはずです)。ただし、GiSTのディスクベースのBツリースタイルのバランスツリーはやり過ぎかもしれません。おそらく、類似のセットを階層的に一緒にクラスタ化したいだけで、既成のクラスタリングアルゴリズムを使用して、ハミング距離(またはより凝ったもの)のようなものを使用してそれを行うことができます。兄弟ノードが類似しているほど、親の境界述語(つまり、それらの和集合を表すセット)が「よりタイト」になります。したがって、検索がより効率的になります。

要約すると、私の提案は:

  • クエリ(ビットベクトル、ハッシュテーブル)との重複をチェックできるように、セットを表現します。
  • 適切な距離(ハミングなど)と市販のアルゴリズムを使用して、セットを階層的にクラスター化します。
  • 各内部ノードで、子ノードセットの和集合を保存します。
  • 検索中、再帰的にトラバースし、ルートがクエリと重複しないセットを持つルートを持つサブツリーを剪定/無視します。

ツリーを動的にする必要がある場合、それを行う方法もたくさんあります。たとえば、ツリーを再帰的にトラバースし、(オーバーラップが最も大きい/ハミング距離が最も小さいノードを通過することにより)最適な場所を見つけ、移動しながらユニオン(境界述語)を更新できます。削除は、おそらくもう少しトリッキーです。オブジェクトを欠落としてマークし、マークされたオブジェクトの数が特定のしきい値に達したときにサブツリー(または構造全体)を再構築することができます。

これがアプリケーションにうまく機能するかどうかは、アプリオリに言うのは難しいかもしれませんが、実験的に確認するのは簡単です。また、微調整の余地がたくさんあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.