我的问题如下
我有一套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
的不同查询。
编辑: 我所谈论的例子: 例如,如果S1中包含S1:检查I中是否包含S1:如果不包含,则不能将S2包括在内(不需要检查) 如果S3是S1和S2的并集:如果S1和S2包含在I中,那么S3
也是如此答案 0 :(得分:1)
您可以使用inverted index方法。虽然它不能改善最坏情况的性能,但它可能会加速平均情况,特别是对于相对密集的查询向量。
对于每个j = 1,2,...,k创建一个排序列表,如果j
在S_i
中,则每个子集都在此列表中。在预处理中仅创建一次。
在您的示例中,它将类似于:
0 -> [S1,S2,S3]
1 -> [S2,S3]
2 -> [S3]
3 -> [S2]
4 -> []
现在,给定一个查询I
,找到包含" down"之一的所有集合。 I
的位。这与信息检索中的OR查询相同。此查询的答案是结果中没有的子集。其余的都是。
在您的示例中,查询为2 OR 4
,查询倒排索引时的结果为:S3
,因此结果为S1,S2。
这基本上就是搜索引擎所做的事情,如果查询与可能性的数量相比包含的条款非常少,则效率非常高。
答案 1 :(得分:1)
以部分答案回答我的问题:
现在的问题是,如何从1)最佳地构建树?即具有最大深度和最小“宽度”的 例如,在我的例子中,“坏”树将是S1,S2和S3是来自根节点的子节点。 “好”树将是根节点仅具有针对子节点的S1,并且以S1为根的树具有S2且S3为子节点。 我不知道如何构建这棵树
答案 2 :(得分:1)
构建一个包含所有T
的二叉树S1...Sn
,其中每个级别k都有两个子节点,具体取决于S
是否有0
或1
位置k
。树的叶子都是你的S1...Sn
。
给定输入子集I
,我们取Ik
(位置k中的元素):如果Ik==0
,则选择T
的子树K
级Ik==1
1}}对应于0.如果T
您在级别K
选择了O(n+k)
的子树。在T上以这种方式进行,直到你到达所有的树叶。
在最糟糕的情况下,您对给定的 I
进行S1...Sn
次操作。
由于T
不会改变,因此构建树T
是一次操作。
n
有超过2^k=m
个叶子,它有S1...Sn
个叶子。但是我们可以删除不在O(2^k)
中的叶子和死亡的子树。这将成本分析带到m
,但实际上我们将拥有更少的节点。现在,分析变得更难,如果值得,取决于n
和S
之间的比率;
我提出了一种不同的分析方法:认为在k级我们在常量时间内将所有子集k
丢弃为O(n)
级别的无效位,但我们必须在{{1}中这样做每个级别的子树。由于此操作重复k
次,因此最高费用为O(kn)
,但实际上平均费用较低。