Wildcard- und Regex-Suche in einem Trie
Unterstützen Sie die Wildcard-Suche mit '.', indem Sie auf dieser Tiefe alle Kinder verfolgen, und lösen Sie damit das Problem der Datenstruktur design-add-and-search-words.
Wildcard- und Regex-Suche in einem Trie ist eine kostenlose DSA Interview Prep-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des DSA Interview Prep-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der DSA Interview Prep-Kurs umfasst insgesamt 4 Lektionen.
Das Problem der Wildcard-Suche
Die Standardsuche in einem Trie verarbeitet exakte Zeichen. Die Wildcard-Suche fügt ein Sonderzeichen '.' hinzu, das jedem einzelnen Zeichen entspricht. Wenn bei der Suche ein '.' angetroffen wird, dürfen wir nicht nur einem bestimmten Kind folgen, sondern müssen alle Kinder ausprobieren — eine Verzweigung. Das ist die zentrale Idee hinter LeetCode 211 „Design Add and Search Words Data Structure“. Jedes '.' vervielfacht die Suchpfade um die Anzahl der Kinder auf dieser Ebene.
Rekursive Wildcard-Suche
Implementieren Sie die Wildcard-Suche mit einer rekursiven DFS-Hilfsfunktion. Für jedes Zeichen im Muster gilt: Handelt es sich um ein Literalzeichen, folgen Sie dem entsprechenden Kind (oder geben Sie False zurück, wenn es fehlt); handelt es sich um '.', rufen Sie die Funktion für alle Kinder rekursiv auf und geben Sie True zurück, sobald einer der Aufrufe erfolgreich ist. Geben Sie am Ende des Musters node.is_end zurück.
class TrieNode:
def __init__(self):
self.children = {}
self.is_end = False
class WordDictionary:
def __init__(self):
self.root = TrieNode()
def addWord(self, word):
node = self.root
for c in word:
if c not in node.children:
node.children[c] = TrieNode()
node = node.children[c]
node.is_end = True
def search(self, word):
def dfs(node, i):
if i == len(word):
return node.is_end
c = word[i]
if c == '.':
return any(dfs(child, i+1) for child in node.children.values())
if c not in node.children:
return False
return dfs(node.children[c], i+1)
return dfs(self.root, 0)
wd = WordDictionary()
wd.addWord('bad')
wd.addWord('dad')
wd.addWord('mad')
print(wd.search('.ad')) # True
print(wd.search('b..')) # True
print(wd.search('pad')) # FalseWarum any() für die Verzweigung verwendet wird
Wenn ein '.' angetroffen wird, rufen wir any(dfs(child, i+1) for child in node.children.values()) auf. Der Generator von any() verwendet eine Kurzschlussauswertung — er beendet die Suche, sobald ein Kind True zurückgibt. Dadurch vermeiden wir unnötige Erkundungen. Im schlimmsten Fall (ein Muster, das vollständig aus '.' besteht) werden alle Pfade erkundet — die Komplexität beträgt O(26^k), wobei k die Anzahl der Punkte ist. Dadurch sind Muster wie '....' bei großen Tries teuer.
Iterative Wildcard-Suche mit Warteschlangen
Ein iterativer Ansatz verwendet eine Warteschlange mit Paaren aus (node, index). Beginnen Sie mit (root, 0). Geben Sie True zurück, wenn für ein Paar index == len(word) und node.is_end gilt. Verarbeiten Sie andernfalls das aktuelle Zeichen: Bei '.' fügen Sie alle Kinder zur Warteschlange hinzu, bei einem Literalzeichen nur das passende Kind. Im Wesentlichen handelt es sich dabei um eine BFS über die Pfade des Tries.
from collections import deque
def search_iterative(root, word):
queue = deque([(root, 0)])
while queue:
node, i = queue.popleft()
if i == len(word):
if node.is_end:
return True
continue
c = word[i]
if c == '.':
for child in node.children.values():
queue.append((child, i+1))
elif c in node.children:
queue.append((node.children[c], i+1))
return False
print('Iterative BFS-based wildcard search')Komplexitätsanalyse der Wildcard-Suche
Bei einem Muster ohne Wildcards beträgt die Laufzeit O(m). Bei einem Muster mit k Wildcards liegt der Worst Case bei O(26^k × m) — die Laufzeit wächst exponentiell mit der Anzahl der Wildcards. In der Praxis sind Wildcards normalerweise selten und der Trie ist flach, sodass die Leistung akzeptabel ist. Bei Mustern, die ausschließlich aus Wildcards bestehen (z. B. beim Abgleich aller Wörter der Länge k), degeneriert die Suche zu einer vollständigen Traversierung des Tries.
Regex-Suche über einstellige Wildcards hinaus
Eine Erweiterung auf vollständige reguläre Ausdrücke (z. B. '*' für null oder mehr Zeichen) erfordert eine andere Verarbeitung. Ein '*' kann jedes Suffix abgleichen. Daher müssen wir beim Auftreten dieses Zeichens alle Trie-Pfade ab dem aktuellen Knoten ausprobieren. Eine echte Regex-Suche in einem Trie ist komplex — sie bleibt normalerweise der Konstruktion von NFA/DFA vorbehalten. In Interviews sind einstellige Wildcards ('.') das Standardmuster.
Glob-Musterabgleich
Glob-Abgleich mit '?' (beliebiges einzelnes Zeichen) und '*' (beliebige Sequenz einschließlich einer leeren Sequenz) lässt sich mit DP implementieren. Bei einer Implementierung in einem Trie entspricht '?' einer Verzweigung auf einer Ebene (wie '.') und '*' einer mehrstufigen DFS. Der kombinierte DP-Ansatz: dp[i][j] = True, wenn pattern[0..i] zu string[0..j] passt. Die interviewende Person gibt normalerweise vor, welche Variante implementiert werden soll.
Praktische Anwendung: IP-Adress-Routing
Wildcards in Tries werden in IP-Routingtabellen verwendet, wobei '*' als Präfix-Wildcard fungiert. Ein Router speichert Routenpräfixe wie '192.168.*' und gleicht eingehende Adressen damit ab. Das Longest-Prefix-Matching (die spezifischste Route gewinnt) wird implementiert, indem der Trie so tief wie möglich durchlaufen und der zuletzt gefundene Treffer verwendet wird. Dies ist eine praktische Anwendung von Präfix- und Wildcard-Operationen auf Tries.
Optimierung: Tote Zweige beschneiden
Wenn ein Trie-Knoten keine Kinder besitzt (also ein Blatt ist) und is_end = False gilt, liefert jede Suche, die ihn erreicht, False. Bei der Wildcard-Suche können Sie diese Sackgassenknoten vor dem rekursiven Aufruf überspringen und so unnötige Aufrufe vermeiden. Wenn jeder Knoten eine word_count-Angabe (die Gesamtzahl der Wörter im Teilbaum) enthält, lässt sich ein vollständiger Teilbaum überspringen, wenn kein Wort die Längenbedingungen des verbleibenden Musters erfüllen kann.
Vollständige WordDictionary-Klasse (interviewtauglich)
Eine übersichtliche, interviewtaugliche WordDictionary-Klasse, die Einfügen und die Suche mit Punkt-Wildcards in einer Klasse kombiniert. Dies ist genau die Implementierung, die für LeetCode 211 erwartet wird. Die rekursive Suche mit dem kurzschlussfähigen any() ist kompakt und zeigt die Verzweigungslogik für Interviewerinnen und Interviewer klar.
class WordDictionary:
def __init__(self):
self.root = {}
def addWord(self, word):
node = self.root
for c in word:
node = node.setdefault(c, {})
node['#'] = True
def search(self, word):
def dfs(node, i):
if i == len(word):
return '#' in node
if word[i] == '.':
return any(dfs(v, i+1) for k, v in node.items() if k != '#')
nxt = node.get(word[i])
return dfs(nxt, i+1) if nxt is not None else False
return dfs(self.root, 0)
wd = WordDictionary()
for w in ['at','and','an','add']:
wd.addWord(w)
print(wd.search('a.')) # True (at, an)
print(wd.search('.nd')) # True (and)
print(wd.search('...')) # True (and, add)
print(wd.search('x.')) # Falsesetdefault für einen kompakten Trie
dict.setdefault(key, default) gibt den Wert für key zurück, falls dieser vorhanden ist, fügt andernfalls default ein und gibt ihn zurück. Die Verwendung von node.setdefault(c, {}) beim Einfügen macht die If-Else-Prüfung überflüssig: Das untergeordnete Dictionary wird bei Bedarf erstellt und in jedem Fall zurückgegeben. Dadurch wird das Einfügen zu einer einzeiligen Traversierung: for c in word: node = node.setdefault(c, {}). Sauber und Pythonic.
Schnelltest
Testen Sie Ihr Verständnis der Konzepte aus Data Structures & Algorithms — Coding Interview Prep aus dieser Lektion.
Zusammenfassung der Lektion
In dieser Lektion haben Sie gelernt: Die Wildcard '.' erfordert an der passenden Position eine Verzweigung auf alle Kinder mithilfe einer rekursiven DFS, die Verwendung von any() mit einem Generator ermöglicht eine Kurzschlussauswertung für den vorzeitigen Abbruch und setdefault ermöglicht das kompakte Einfügen in einen Trie mit einer einzigen Zeile. Als Nächstes kombinieren wir Trie und Backtracking, um Word Search II zu lösen — mehrere Wörter gleichzeitig auf einem 2D-Spielfeld zu finden.
Häufig gestellte Fragen
Ist die Lektion „Wildcard- und Regex-Suche in einem Trie“ kostenlos?
Ja — der vollständige Text von „Wildcard- und Regex-Suche in einem Trie“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des DSA Interview Prep-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der DSA Interview Prep-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Wildcard- und Regex-Suche in einem Trie“?
Unterstützen Sie die Wildcard-Suche mit '.', indem Sie auf dieser Tiefe alle Kinder verfolgen, und lösen Sie damit das Problem der Datenstruktur design-add-and-search-words. Du übst DSA Interview Prep mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um DSA Interview Prep zu starten?
Keine Vorkenntnisse erforderlich. DSA Interview Prep auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.
Wie lange dauert die Lektion „Wildcard- und Regex-Suche in einem Trie“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser DSA Interview Prep-Lektion Code schreiben und ausführen?
Ja. Jede DSA Interview Prep-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- TrieNode-Klasse: Einfügen und Suchen
- Präfixsuche und Starts-With
- Wildcard- und Regex-Suche in einem Trie
- Word Search II: Trie und Backtracking auf einem Gitter