По сути, Unwind верен тем, что есть много разных способов реализовать дерево; а для большого масштабируемого дерева вложенные словари могут стать громоздкими или, по крайней мере, неэффективно занимать место. Но поскольку вы только начинаете, я думаю, что это самый простой подход; вы можете написать простой код trie
всего в несколько строк. Во-первых, функция для построения дерева:
>>> _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_'}}}}
Если вы не знакомы с ним setdefault
, он просто ищет ключ в словаре (здесь letter
или _end
). Если ключ присутствует, он возвращает связанное значение; если нет, он присваивает этому ключу значение по умолчанию и возвращает значение ( {}
или _end
). (Это похоже на версию, get
которая также обновляет словарь.)
Затем функция для проверки, есть ли слово в дереве:
>>> 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
Я оставлю вам вставку и удаление в качестве упражнения.
Конечно, предложение Unwind было бы не намного сложнее. Может быть небольшой недостаток скорости в том, что для поиска правильного подузла потребуется линейный поиск. Но поиск будет ограничен количеством возможных символов - 27, если мы включим _end
. К тому же, как он предлагает, создание огромного списка узлов и доступ к ним по индексу ничего не даст; вы можете просто вложить списки.
Наконец, я добавлю, что создание ориентированного ациклического графа слов (DAWG) было бы немного сложнее, потому что вы должны обнаруживать ситуации, в которых ваше текущее слово имеет суффикс с другим словом в структуре. Фактически, это может быть довольно сложно, в зависимости от того, как вы хотите структурировать DAWG! Возможно, вам придется кое-что узнать о расстоянии Левенштейна, чтобы понять это правильно.