Все рассматриваемые множества являются подмножествами известного конечного множества, скажем, {0..10 ^ 4}.
Давайте назовем это N = 10 ^ 4. Это достаточно мало, и это окажется полезным. Допустим, у вас есть наборы S.
«Логически» это означает, что у вас есть матрица N * S.
У вас уже будет набор наборов. В этой первичной структуре есть S наборов.
10 ^ 4 достаточно мал, чтобы вы могли поддерживать вторичную структуру данных, в которой для каждого значения N хранится список наборов , в котором она находится. Эта структура вроде как транспонирование первичной структуры. Это может быть вектор длины N, позволяющий искать в постоянном времени список наборов, в которых находится конкретное значение.
Теперь, когда вы добавите новый набор, можно будет использовать эту вторичную структуру, чтобы найти, в каких других наборах содержится каждое из его значений. Например, мы добавляем новый набор со значениями 2,5, 10
new_set = {2,5,10}
Вторичная структура сообщает нам, в каких наборах они находятся:
2 : {A,B,D}
5 : {B,D}
10 : {B}
Мы можем объединить и отсортировать эти три списка, чтобы получить ABBBDD
, который говорит нам не только о том, какие наборы перекрываются, но и о размере перекрытий. Три узла совместно используются с B, что означает, что наш новый набор является подмножеством или равен B. Мы совместно используем 1 узел с A и два узла с D. Если окажется, что общий размер A равен 1, тогда мы теперь знаем, что A является подмножеством нашего нового набора.