Ich suche nach einer Datenstruktur , dass speichert einen Satz von Saiten über einen Zeichensatz , können die folgenden Operationen durchführen. Wir bezeichnen D ( S ) als die Datenstruktur, die den Satz von Zeichenketten S speichert .
Add-Prefix-Set
on : Bei gegebener Menge T von (möglicherweise leeren) Zeichenfolgen, deren Größe durch eine Konstante und deren Zeichenfolgenlänge durch eine Konstante begrenzt ist, wird D zurückgegeben ( { t s | t ∈ T , s ∈ S } ) . Diese beiden Begrenzungskonstanten sind global: Sie sind für alle Eingänge T gleich .Get-Prefixes
zu : return { a | ein s ∈ S , a ∈ & Sgr; } . Beachten Sie, dass es mir nichts ausmacht, welche Struktur für diese Menge verwendet wird, solange ich den Inhalt in O ( | Σ | ) aufzählen kann .Remove-Prefixes
auf : return D ( { s | a s ∈ S , a ∈ & Sgr; } ) .Merge
: Da und D ( T ) , return D ( S ∪ T ) .
Nun, ich würde wirklich gerne alle diese Operationen in Zeit ausführen , aber ich bin mit einer Struktur einverstanden, die alle diese Operationen in O ( n ) Zeit ausführt , wobei n die Länge der längsten Zeichenfolge in der Zeichenfolge ist Struktur. Im Falle der Zusammenführung, würde Ich mag eine O ( n 1 + n 2 ) Laufzeit, wobei n 1 ist , n für die erste und n 2 der n für die zweite Struktur.
Eine zusätzliche Anforderung ist, dass die Struktur unveränderlich ist oder dass die obigen Operationen 'neue' Strukturen zurückgeben, so dass Zeiger auf die alten weiterhin wie zuvor funktionieren.
Ein Hinweis zur Amortisation: Das ist in Ordnung, aber Sie müssen auf Ausdauer achten. Da ich alte Strukturen immer wieder verwende, habe ich Probleme, wenn ich einen Worst-Case-Fall mit bestimmten Operationen auf derselben Struktur erleide (ignoriere also die neu erstellten Strukturen).
Ich möchte eine solche Struktur in einem Parsing-Algorithmus verwenden, an dem ich arbeite. Die obige Struktur würde den Lookahead enthalten, den ich für den Algorithmus benötige.
Ich habe bereits überlegt, einen Trie zu verwenden , aber das Hauptproblem ist, dass ich nicht weiß, wie ich Versuche effizient zusammenführen kann. Wenn der Satz von Zeichenfolgen für Add-Prefix-Set
nur aus Zeichenfolgen mit einem Zeichen besteht, können Sie diese Sätze in einem Stapel speichern, wodurch Sie -Laufzeiten für die ersten drei Vorgänge erhalten. Dieser Ansatz funktioniert jedoch auch nicht für das Zusammenführen.
Schließlich ist zu beachten , dass ich nicht in Faktoren interessiert bin : das ist konstant für alles, was mich interessiert.
quelle
Add-Prefix-Set
oder beginnen Sie mit einem beliebigen Satz von Zeichenfolgen?Add-Prefix-Set
in)Antworten:
Ich habe lange nachgedacht, aber nicht das Problem gefunden, alle Operationen in einer trie-artigen DAG-Struktur so dumm wie möglich durchzuführen:
Add-Prefix-Set
Verschmelzen
Vereinigen Sie Wurzeln zweier Strukturen: Machen Sie alle Kindknoten der zweiten Wurzel zum Kindknoten des ersten Knotens. Möglicherweise sind jetzt mehrere Kanten mit demselben Zeichen markiert, die vom selben Knoten ausgehen.
Lazy Update der Wurzel
Get-Präfixe
Faul aktualisieren Sie die Wurzel. Finden Sie nun alle Kinder der Wurzel und melden Sie Buchstaben an den Kanten, die zu ihnen führen.
Präfixe entfernen
Faul aktualisieren Sie die Wurzel. Vereinige alle Kinder der Wurzel und setze den Wurzelzeiger auf das Ergebnis dieser Vereinigung. Faul aktualisieren Sie die neue Wurzel.
Beharrlichkeit
quelle