Angenommen, alle Ihre Mengen sind endliche Teilmengen von N. LassenS⊆P(N) bezeichnen Ihre Menge von Mengen.
Sie möchten zwei Operationen:
O1(S,s′): Für jeden s′⊆N, hinzufügen s′ zu S
O2(S,s′): Für jeden s′⊆N, gibt es einige s∈S damit s⊆s′?
Hier sind einige Ideen, um die Dinge zu beschleunigen:
Sie werden testen, ob eine Menge eine Teilmenge einer anderen ist, also sollten Sie wahrscheinlich die Größe beibehalten |s| von jedem Satz s verfügbar in O(1) so dass, wenn Sie testen müssen, ob s⊆s′Sie überprüfen zunächst, ob |s|≤|s′|und wenn nicht, können Sie sofort false zurückgeben. Und das hast du tatsächlich|s|≤|s′|Dann führen Sie einfach den normalen langsamen Test aus.
Beachten Sie, dass, wenn Sie haben s1∈S und s2∈S, damit s1⊆s2, dann wenn s2⊆s′, Sie haben auch s1⊆s′. Sie müssen also nicht behaltens2 im S zum O2. So können Sie darstellenS durch eine Reihe von Mengen, so dass s∈S und s⊊s′bedeutet . Mit anderen Worten, Sie müssen nur die Mengen in verfolgen , die für die Aufnahme minimal sind. Dies kann ziemlich effizient implementiert werden: Beim Hinzufügen einer Menge für alle Mengen so dass(geordnet nach zunehmendem Kardinal), wenn , dann füge nicht hinzu da es nicht minimal ist (oder bereits in ). Andernfalls addiere und dann zwischen den Mengen so dassEntfernen Sie diese so, dass (weil sie nicht mehr minimal sind).s′∉SSs′s∈S|s|≤|s′|s⊆s′s′Ss′s∈S|s′|<|s|s′⊆s
Behalten Sie eine Menge , die der Vereinigung aller Mengen in . Dann wird anstelle der laufenden , können Sie laufen statt (weil , wenn für einige , , dann da , und, wenn , dann ).tSO2(S,s′)O2(S,s′∩t)s∈Ss⊆s′s⊆ts⊆s′∩ts⊆s′∩ts⊆s′∩t⊆s′
Unter Berücksichtigung dieser Ideen würde ich durch ein Wörterbuch darstellen (implementiert als doppelt verknüpfte Liste von Paaren mit den Schlüsseln in aufsteigender Reihenfolge) so dass eine doppelt verknüpfte Liste ist, die genau das enthält minimale (zur Aufnahme) Mengen in von Kardinal .S(key,value)dd(k)Sk
O1(S,s')
if O2(S,s')
return
if d(k) doesn't exist
d(k) := new_doubly_linked_list()
add(d(k),s')
S.t := union(S.t, s')
for each key k of d so that |s'|+1 <= k
for s in d(k)
if subset(s', s)
remove s
_O2(S,s')
for each key k of d so that k <= |s'|
for s in d(k)
if subset(s,s')
return true
return false
O2(S,s')
return _O2(S,inter(S.t,s'))
(Beachten Sie, dass Sie, obwohl ich es im Code von nicht explizit O1
getan habe, eine einzelne Durchquerung der doppelt verknüpften Liste durchführen können, die darstellt d
)
Ich denke nicht, dass sich dies im schlimmsten Fall zu sehr verbessert, aber im Durchschnitt sollte es so sein.