簡體   English   中英

快速檢查子集是否包含給定的子集列表的方法

[英]fast way to check if subset contains a given list of subsets

我的問題如下

我有一套K元素

該集合的每個子集由std :: bitset的實例表示(位i為真=子集中有元素i)

我有一個輸入子集I,以及一個子集S1 ... Sn的列表

我想從S1 ... Sn中返回項目,這樣Si就包含在I中。(也就是說,每次Si有一點真實,它在I中也必須是真的)

顯然,這可以在K * n中完成,通過對每個S子集進行獨立的相同檢查。

但是,有沒有一種通用的方法可以做得更好? 我很確定這是可能的,因為在我的情況下,子集列表S1 ... Sn總是相同的並且可以進行預處理。 我確定可以將子集存儲在特定的數據結構中(樹?trie?),這樣我就可以一次性丟棄很多相同的數據結構等等。

example :
K = 5

I = [1,1,0,1,0]

S1 = [1,0,0,0,0]
S2 = [1,1,0,1,0]
S3 = [1,1,1,0,0]

the ouput should return S1,S2 (not S3!)

我有一個常數集S1,S2,...,Sn ,並在同一組上運行不同的I查詢。

編輯:我正在談論的例子:例如,如果S2包含在S2中:檢查I中是否包含S1:如果不包括,那么如果S3是S1的並集,則S2不能包含在I中(不需要檢查) S2:如果S1和S2包含在I中,則S3也是如此

您可以使用倒排索引方法。 雖然它不會改善最壞情況的性能,但它可能會加速平均情況,特別是對於相對密集的查詢向量。

對於每個j = 1,2,...,k,創建一個排序列表,其中如果jS_i ,則每個子集都在此列表中。 在預處理中僅創建一次。

在您的示例中,它將類似於:

0 -> [S1,S2,S3]
1 -> [S2,S3]
2 -> [S3]
3 -> [S2]
4 -> []

現在,給定一個查詢I發現,包括“下降”位中的一個所有集合I 這與信息檢索中的OR查詢相同。 此查詢的答案是結果中沒有的子集。 剩下的就是。

在您的示例中,查詢為2 OR 4 ,查詢反向索引時的結果為: S3 ,因此結果為S1,S2。


這基本上就是搜索引擎所做的事情,如果查詢與可能性的數量相比包含的條款非常少,則效率非常高。

用部分答案回答我的問題:

  1. 從S1 ... Sn我們構建一個子集樹,使得根節點是空子集(bitset中的全0),並且每個子節點包含其父子集
  2. 對於算法,從根開始:
    • 為每個孩子:
      • 如果此節點上的子集包含在I中,則添加此子集並再次以此節點作為根調用算法
      • 否則,轉到下一個孩子(從未處理過這個孩子的子樹)

現在問題是,如何從1)最佳地構建樹? 即,具有最大深度和最小“寬度”的例如,在我的例子中,“壞”樹將是S1,S2和S3是來自根節點的子節點。 “好”樹將是根節點僅具有針對子節點的S1,並且以S1為根的樹具有S2且S3為子節點。 我不知道如何構建這棵樹

構造具有所有S1...Sn的二叉樹T ,其中每個級別k具有兩個子節點,這取決於S在位置k0還是1 樹的葉子都是你的S1...Sn

給定輸入子集I讓我們取Ik (位置k中的元素):如果Ik==0 ,則在級別K對應於0的T的子樹。如果Ik==1 ,則在級別K選擇T子樹。 在T上以這種方式進行,直到你到達所有的葉子。

在最壞的情況下,您對給定的I進行O(n+k)運算。

由於S1...Sn不會改變,因此構造樹T是一次操作。

編輯:我的答案很倉促。 T具有多於n葉子,它具有2^k=m葉子。 但我們可以刪除不在S1...Sn中的葉子S1...Sn和死亡的子樹。 這將成本分析帶到O(2^k)但實際上我們將有更少的節點。 現在分析變得更難,如果它的價值取決於mn之間的比率;

我提出了一種不同的分析方法:認為在k級我們在恆定時間內丟棄所有在級別為k無效位的子集S ,但是我們必須在每個級別的O(n)子樹中這樣做。 由於該操作重復k次,因此最大成本為O(kn) ,但實際上平均值較低。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM