Abwickeln ist im Wesentlichen richtig, dass es viele verschiedene Möglichkeiten gibt, einen Versuch zu implementieren; und für einen großen, skalierbaren Versuch können verschachtelte Wörterbücher umständlich werden - oder zumindest platzsparend. Aber da Sie gerade erst anfangen, denke ich, dass dies der einfachste Ansatz ist. Sie könnten eine einfache trie
in nur wenigen Zeilen codieren . Zunächst eine Funktion zum Konstruieren des Versuchs:
>>> _end = '_end_'
>>>
>>> def make_trie(*words):
... root = dict()
... for word in words:
... current_dict = root
... for letter in word:
... current_dict = current_dict.setdefault(letter, {})
... current_dict[_end] = _end
... return root
...
>>> make_trie('foo', 'bar', 'baz', 'barz')
{'b': {'a': {'r': {'_end_': '_end_', 'z': {'_end_': '_end_'}},
'z': {'_end_': '_end_'}}},
'f': {'o': {'o': {'_end_': '_end_'}}}}
Wenn Sie nicht vertraut sind setdefault
, wird einfach ein Schlüssel im Wörterbuch nachgeschlagen (hier letter
oder _end
). Wenn der Schlüssel vorhanden ist, wird der zugehörige Wert zurückgegeben. Wenn nicht, weist es diesem Schlüssel einen Standardwert zu und gibt den Wert ( {}
oder _end
) zurück. (Es ist wie eine Version davon get
, die auch das Wörterbuch aktualisiert.)
Als nächstes eine Funktion zum Testen, ob das Wort im Versuch ist:
>>> def in_trie(trie, word):
... current_dict = trie
... for letter in word:
... if letter not in current_dict:
... return False
... current_dict = current_dict[letter]
... return _end in current_dict
...
>>> in_trie(make_trie('foo', 'bar', 'baz', 'barz'), 'baz')
True
>>> in_trie(make_trie('foo', 'bar', 'baz', 'barz'), 'barz')
True
>>> in_trie(make_trie('foo', 'bar', 'baz', 'barz'), 'barzz')
False
>>> in_trie(make_trie('foo', 'bar', 'baz', 'barz'), 'bart')
False
>>> in_trie(make_trie('foo', 'bar', 'baz', 'barz'), 'ba')
False
Ich überlasse Ihnen das Einfügen und Entfernen als Übung.
Natürlich wäre der Vorschlag von Unwind nicht viel schwieriger. Es könnte einen leichten Geschwindigkeitsnachteil geben, wenn das Finden des richtigen Unterknotens eine lineare Suche erfordern würde. Die Suche wäre jedoch auf die Anzahl der möglichen Zeichen beschränkt - 27, wenn wir einschließen _end
. Es gibt auch nichts zu gewinnen, wenn Sie eine umfangreiche Liste von Knoten erstellen und über einen Index darauf zugreifen, wie er vorschlägt. Sie können die Listen auch einfach verschachteln.
Abschließend möchte ich hinzufügen, dass das Erstellen eines gerichteten azyklischen Wortgraphen (DAWG) etwas komplexer wäre, da Sie Situationen erkennen müssen, in denen Ihr aktuelles Wort ein Suffix mit einem anderen Wort in der Struktur teilt. Tatsächlich kann dies ziemlich komplex werden, je nachdem, wie Sie die DAWG strukturieren möchten! Möglicherweise müssen Sie einige Dinge über die Levenshtein- Entfernung lernen , um es richtig zu machen.