Следующая стратегия должна быть достаточно эффективной. Я использовал варианты этого для пересечения восходящих последовательностей в ряде случаев.
Сначала я предполагаю, что у вас есть какая-то очередь приоритетов (если нет, то сворачивание вашей собственной кучи довольно просто). И быстрый поиск ключа / значения (btree, hash, что угодно).
С учетом вышесказанного, вот псевдокод для алгоритма, который должен делать то, что вы хотите достаточно эффективно.
# Initial setup
sets = array of all sets
intersection_count = key/value lookup with keys = (set_pos, set_pos) and values are counts.
p_queue = priority queue whose elements are (set[0], 0, set_pos), organized by set[0]
# helper function
def process_intersections(current_sets):
for all pairs of current_sets:
if pair in intersection_count:
intersection_count[pair] += 1
else:
intersection_count[pair] = 1
# Find all intersections
current_sets = []
last_element = first element of first thing in p_queue
while p_queue is not empty:
(element, ind, set_pos) = get top element from p_queue
if element != last_element:
process_intersections(current_sets)
last_element = element
current_sets = []
current_sets.append(set_pos)
ind += 1
if ind < len(sets[set_pos]):
add (sets[set_pos][ind], ind, set_pos) to p_queue
# Don't forget the last one!
process_intersections(current_sets)
final answer = []
for (pair, count) in intersection_count.iteritems():
if k-1 < count:
final_answer.append(pair)
Время выполнения будет O(sum(sizes of sets) * log(number of sets) + count(times a point is in a pair of sets)
. В частности, обратите внимание, что если два набора не имеют пересечения, вы никогда не пытаетесь пересечь их.