如何为其最大的超集分配许多子集?

时间:2017-05-12 00:09:47

标签: algorithm

我的数据有很多套(几百万)。这些设置大小中的每一个都在几个成员到几万个整数之间。其中许多集合是较大集合的子集(有许多超集)。我正在尝试将每个子集分配给它最大的超集。

任何人都可以为这类任务推荐算法吗? 有许多算法可用于生成集合的所有可能子集,但鉴于我的数据大小(例如paperSO question),此类方法的时间禁止。

我的数据集示例:

A {1, 2, 3}
B {1, 3}
C {2, 4}
D {2, 4, 9}
E {3, 5}
F {1, 2, 3, 7}

预期答案:B和A是F的子集(不重要的是B也是A的子集); C是D的子集; E仍未分配。

3 个答案:

答案 0 :(得分:2)

这是一个可能有用的想法:

  • 构建一个表格,将数字映射到已排序的集合列表,首先按大小排序,然后按大小排序,然后按大小排序,任意但具有一些规范顺序。 (按设置名称的字母顺序说。)因此,在您的示例中,您有一张表格,其中1映射到[F, A, B]2映射到[F, A, D, C],{{ 1}}到3等等。这可以实现[F, A, B, E]时间,其中O(n log n)是输入的总大小。
  • 对于输入中的每个集合:
    • 获取与该集合中每个条目关联的列表。因此,对于n,您将获得与1,2和3相关联的列表。您在整个算法的运行时中发出的选择总数为O(n),因此到目前为止,运行时是O(n log n + n),它仍然是O(n log n)。
    • 现在同时走下每个列表。如果集合是所有三个列表中的第一个条目,那么它是包含输入集的最大集合。输出该关联并继续下一个输入列表。如果没有,则丢弃输入列表中所有项目中的最小项目,然后重试。实现这最后一点很棘手,但你可以将所有列表的头部存储在堆中,并获得(IIRC)像O(n log k)整体运行时的东西,其中k是任何单个集合的最大大小,所以你可以绑定在最坏的情况下,在O(n log n)处。

因此,如果我把所有内容都弄清楚,那么算法的运行时总体上是O(n log n),这看起来可能就像你要解决这个问题一样好。

这是算法的python实现:

A

注意:不要太信任我的写作。我刚才想到了这个算法,我还没有证明它是正确的还是其他任何东西。

答案 1 :(得分:0)

所以你有数百万套,每套都有数千个元素。只表示该数据集需要数十亿个整数。在你的比较中,你甚至可以毫不费力地进行数万亿次操作。

因此,我假设你需要一个能够分布在很多机器上的解决方案。这意味着我会考虑https://en.wikipedia.org/wiki/MapReduce。一系列的。

  1. 阅读这些集合,将它们映射到i: s的k:v对,其中i是集合s的元素。
  2. 接收整数的键以及集合列表。将它们映射到成对(s1, s2): i,其中s1 <= s2都是包含在i中的集合。不要忽略将每个集合映射为自己配对!
  3. 对于每对(s1, s2)计算交叉点的大小k,并发送对s1: ks2: k。 (如果s1s2不同,则只发送第二个。
  4. 每组s都会收到一组超集。如果是最大值,请发送s: s。否则,请为t: s严格超集的t发送s
  5. 对于每个集s,只有在最大值时才会接收列表集s。如果s最大,请为t: s的子集t发送s
  6. 对于每个集合,我们会收到它是其子集的最大集合集。 (可能有很多。)
  7. 这有很多步骤,但从本质上讲,它需要在成对的集合之间重复比较,每个集合都有一个共同的元素。可能是O(n * n * m)n是集合数,m是多个集合中不同元素的数量。

答案 2 :(得分:0)

以下是一个算法的简单建议,该算法可能会根据您的数字给出更好的结果(n = 10 ^ 6到10 ^ 7集合,m = 2到10 ^ 5个成员,很多超级/子集)。当然,这很大程度上取决于您的数据。一般而言,复杂性比其他提出的算法差得多。也许你只能处理小于X的集合,例如其他1000个成员使用其他方法。

  1. 按照大小对集进行排序。

  2. 删除第一个(最小的)集并开始将其与后面的其他集进行比较(最大集合优先)。

  3. 找到超集后立即停止并创建关系。如果没有找到超集,请删除。

  4. 重复2.和3.除了最后一组之外的所有内容。