Berechnen Sie die Höhe eines Radixbaums

8

Einführung

Ein Radix-Baum , auch als komprimierter Trie- oder komprimierter Präfixbaum bezeichnet, ist eine baumartige Datenstruktur zum Speichern einer Reihe von Zeichenfolgen. Die Kanten des Baums sind durch nicht leere Zeichenfolgen gekennzeichnet, und jeder Knoten ist entweder terminal oder nicht terminal. Die Zeichenfolgen, die der Baum enthält, sind genau die Beschriftungen aller Pfade vom Stamm zu einem Endknoten. Der Baum muss in der normalen Form vorliegen, die durch die folgenden Bedingungen definiert ist:

  • Alle nicht terminalen Nicht-Wurzelknoten haben mindestens zwei Kinder.
  • Für jeden Knoten haben alle ausgehenden Kanten unterschiedliche erste Zeichen.

Zum Beispiel ist hier der radix Baum den Satz enthält ["test", "testing", "tested", "team", "teams", "technical", "sick", "silly"], wobei (N)die einen Nicht - Terminal - Knoten und (T)einen Endknoten:

-(N)-te-(N)-st-(T)-ing-(T)
  |      |      | 
  |      |      +-ed-(T)
  |      |
  |      +-am-(T)-s-(T)
  |      |
  |      +-chnical-(T)
  |
  +-si-(N)-ck-(T)
        |
        +-lly-(T)

Bei dieser Herausforderung besteht Ihre Aufgabe darin, die Höhe des Baums anhand der Zeichenfolgen als Eingabe zu berechnen.

Eingang

Ihre Eingabe ist eine nicht leere Liste von Zeichenfolgen aus ASCII-Kleinbuchstaben. Es enthält keine Duplikate, kann jedoch in beliebiger Reihenfolge vorliegen. Es kann die leere Zeichenfolge enthalten. Sie können die Eingabe in jedem vernünftigen Format vornehmen.

Ausgabe

Ihre Ausgabe ist die Länge des längsten Wurzel-Blatt-Pfades im entsprechenden Radix-Baum, gemessen in der Anzahl der darin enthaltenen Knoten.

Im obigen Beispiel ist die korrekte Ausgabe 4, entsprechend den Pfaden

(N)-te-(N)-st-(T)-ing-(T)
(N)-te-(N)-st-(T)-ed-(T)
(N)-te-(N)-am-(T)-s-(T)

die 4 Knoten enthalten.

Weitere Beispiele

Hier sind einige weitere Beispiele für Radixbäume:

[""]
-(T)

["","fuller"]
-(T)-fuller-(T)

["","full","fuller"]
-(T)-full-(T)-er-(T)

["full","fuller"]
-(N)-full-(T)-er-(T)

["full","filler"]
-(N)-f-(N)-ull-(T)
        |
        +-iller-(T)

Regeln und Wertung

Sie können ein vollständiges Programm oder eine Funktion schreiben. Dies ist Code Golf, daher gewinnt die niedrigste Byteanzahl.

Sie können beliebige integrierte Funktionen oder Bibliotheken verwenden. Denken Sie jedoch daran, alle imports usw. in Ihre Byteanzahl aufzunehmen. Bibliotheken von Drittanbietern - solche, die nicht in der Standardinstallation Ihrer Sprache enthalten sind - sind zulässig, müssen jedoch separat im Header aufgeführt werden, z. B. Python + pytrie0.2, 60 Byte .

Testfälle

[""] -> 1
["fuller"] -> 2
["","fuller"] -> 2
["","full","fuller"] -> 3
["full","fuller"] -> 3
["full","filler"] -> 3
["full","filler","filter"] -> 4
["full","filler","fi","filter"] -> 5
["test","testing","tested","team","teams","technical","sick","silly"] -> 4
["a","aaaa","aabbaa","aabbaab","abaaa","aab","aabbb","aabba"] -> 8
["dbdbaca","ab","a","caaabaaa","adbbabdb","dbdbdbaca","dbbadbacaba","db"] -> 4
["db","dbbdbb","dbaa","cabcacaa","","acaabcacab","b","abaaaca","bacaaaaa"] -> 3
["aabaabdbb","bacaabadbbdb","abb","aabaa","ab","bcadbb","adbbcaaadbbb","caaa","bbdbcacadbab","dbbdbdb"] -> 4
["bbcaaabbbabbcadbbacadbbdbdb","b","bbbbaaaaaababa","ca","bb","bdbbacadbbdbbdbbababaacaca","abbaabbabcabaaa","bbbacacacabcacacabaaabb","bbcaaaab","bbbbcaacaadbcaaa","babbabcadbdbacacabbcacab","abcabbbaacadbcadb","bbcabbcadbcacaacaadbadbcaadb","dbbbdbbdbacaabbacabcadbdbacaca","bbaabdbdb","cabcadbbbadbadbbaadbcaca","adbadbadbdbcacadbdbbcaadbcaca","abaabbcab","aaabcaabcaab","bacacabcacaacadbadbb"] -> 6
Zgarb
quelle
In Ihrem ersten Beispiel sollte "am" von einem Knoten mit zwei Kindern gefolgt werden, eines mit - "" - (T) und das andere mit - "s" - (T). (Vergleichen Sie im zweiten Beispiel auf der Seite, mit der Sie verlinkt haben, mit "langsam" / "langsam".) Dies hat jedoch keinen Einfluss auf die Länge des längsten Pfades von Wurzel zu Blatt.
Greg Martin
@ GregMartin Die Wikipedia-Seite hat eine etwas andere Implementierung. Ich finde, dass dieser natürlicher ist, und wie Sie sagten, hat er keinen Einfluss auf die Höhe.
Zgarb

Antworten:

2

JavaScript (Firefox 30-57), 137 Byte

f=(a,b=["",...a],s=new Set(b.map(w=>w[0])))=>b.length>1?(s.size>1)+Math.max(...(for(c of s)f(a,[for(w of b)if(w&&w[0]==c)w.slice(1)]))):1

Es muss etwas mit meinem Algorithmus nicht stimmen, da ich anscheinend einen leeren String-Parameter im Sonderfall haben muss.

Neil
quelle
In meiner Referenzlösung ist die leere Zeichenfolge ebenfalls ein Sonderfall. Dies liegt daran, dass der Stammknoten seine eigenen Regeln hat.
Zgarb
Ich musste es auch irgendwie als Sonderfall verwenden, aber dieser Sonderfall ist nur ein einzelnes Zeichen in meiner Lösung (das .am Ende der ersten Zeile).
Martin Ender
1

Netzhaut , 69 55 Bytes

Der nachlaufende Zeilenvorschub ist signifikant.

m`.(?<=(?=\D*^\1(?!\2))\D*^(.*)(.))|^.
:$&
T`w
O`
A-2`

Die Eingabe ist eine durch Zeilenvorschübe getrennte Liste.

Die Leistung kann erheblich gesteigert werden, indem in der ersten Zeile ein \Avor dem letzten \Deingefügt wird.

Erläuterung

Ein Knoten wird an drei Stellen in ein Wort eingefügt:

  • Der Anfang.
  • Nach jedem längsten Präfix, das mit einem anderen Wort geteilt wurde. Das heißt, ein gemeinsames Präfix, nach dem sich die beiden Wörter unterscheiden.
  • Das Ende.

In Retina ist die Produktion in der Regel kürzer, N+1wenn Sie die NDinge gezählt haben. Daher ignorieren wir die am Ende. Für den Fall der leeren Eingabe müssen wir dann aber auch den Start ignorieren, da Anfang und Ende gleich sind.

Um die eigentliche Zählung durchzuführen, fügen wir :an jeder Stelle ein, an der sich ein Knoten befindet. Dann finden wir einfach die maximale Anzahl von :in einem Wort und geben das Plus 1 zurück. So macht es der Code:

m`.(?<=(?=\D*^\1(?!\2))\D*^(.*)(.))|^.
:$&

Dies erkennt alle Knoten. Es passt zu einem Charakter. Dann gibt es ein Lookbehind ein, das dieses Zeichen in einer Gruppe 2und das Präfix davor in einer Gruppe erfasst 1. Dann geht es bis zum Anfang der Zeichenfolge, um einen Lookahead zu starten, der überprüft, ob das Präfix an einer Stelle gefunden werden kann, an der das erfasste Zeichen nicht folgt. Wenn wir diese Übereinstimmung finden, fügen wir ein :vor dem Zeichen ein. Wir stimmen auch mit dem ersten Zeichen des aktuellen Wortes überein, um :am Anfang nicht leerer Wörter ein einzufügen .

T`w

Dies entfernt alle Buchstaben und lässt nur die :.

O`

Dadurch werden die Linien sortiert und die maximale Tiefe erreicht.

A-2`

Dadurch werden alle bis auf die letzte Zeile verworfen.

Und die leere Zeile am Ende zählt die Anzahl der leeren Übereinstimmungen in dieser Zeile, was eins mehr ist als die Anzahl der Doppelpunkte darin.

Probieren Sie es online aus! (Die erste Zeile aktiviert eine durch Zeilenvorschub getrennte Testsuite, bei der jeder Testfall stattdessen eine Kommatrennung verwendet.)

Martin Ender
quelle