Interesują mnie try i DAWG (bezpośredni acykliczny graf słów) i dużo o nich czytałem, ale nie rozumiem, jak powinien wyglądać plik wyjściowy lub plik DAWG.
- Czy trie powinno być przedmiotem zagnieżdżonych słowników? Gdzie każda litera jest podzielona na litery i tak dalej?
- Czy wyszukiwanie w takim słowniku byłoby szybkie, gdyby było 100 000 czy 500 000 wpisów?
- Jak zaimplementować bloki słów składające się z więcej niż jednego słowa oddzielonego
-
spacją? - Jak połączyć prefiks lub sufiks słowa z inną częścią w strukturze? (dla DAWG)
Chcę zrozumieć najlepszą strukturę wyjściową , aby dowiedzieć się, jak ją utworzyć i używać.
Byłbym również wdzięczny za to, co powinno być wyjściem DAWG wraz z trie .
Nie chcę widzieć reprezentacji graficznych z bąbelkami połączonymi ze sobą, chcę poznać obiekt wyjściowy, gdy zestaw słów zostanie przekształcony w próby lub DAWG.
Odpowiedzi:
Unwind jest zasadniczo poprawne, ponieważ istnieje wiele różnych sposobów realizacji próby; a w przypadku dużej, skalowalnej próby, zagnieżdżone słowniki mogą stać się nieporęczne - lub przynajmniej nieefektywne pod względem miejsca. Ale ponieważ dopiero zaczynasz, myślę, że to najłatwiejsze podejście; możesz zakodować prosty
trie
w zaledwie kilku wierszach. Najpierw funkcja do skonstruowania trie:Jeśli nie jesteś zaznajomiony z tym
setdefault
, po prostu wyszukuje klucz w słowniku (tutajletter
lub_end
). Jeśli klucz jest obecny, zwraca skojarzoną wartość; jeśli nie, przypisuje domyślną wartość do tego klucza i zwraca wartość ({}
lub_end
). (To tak, jakby wersjaget
tego również aktualizowała słownik).Następnie funkcja sprawdzająca, czy słowo znajduje się w trie:
Wkładanie i wyjmowanie pozostawiam tobie jako ćwiczenie.
Oczywiście sugestia Unwind nie byłaby dużo trudniejsza. Może wystąpić niewielka wada szybkości polegająca na tym, że znalezienie właściwego węzła podrzędnego wymagałoby przeszukiwania liniowego. Ale wyszukiwanie byłoby ograniczone do liczby możliwych znaków - 27, jeśli uwzględnimy
_end
. Poza tym nie ma nic do zyskania tworząc ogromną listę węzłów i uzyskując do nich dostęp za pomocą indeksu, jak sugeruje; równie dobrze możesz po prostu zagnieździć listy.Na koniec dodam, że utworzenie skierowanego acyklicznego grafu słów (DAWG) byłoby nieco bardziej złożone, ponieważ musisz wykryć sytuacje, w których twoje obecne słowo ma w strukturze przyrostek z innym słowem. W rzeczywistości może to być dość skomplikowane, w zależności od tego, jak chcesz zbudować DAWG! Być może będziesz musiał dowiedzieć się czegoś o dystansie Levenshteina, aby to naprawić.
źródło
dict.setdefault()
(jest niewykorzystany i niezbyt dobrze znany), po części dlatego, że pomaga zapobiegać błędom, które są zbyt łatwe do utworzenia za pomocądefaultdict
(gdzie nie dostanieszKeyError
dla nieistniejących kluczy podczas indeksowania). Jedyną rzeczą, która sprawiłaby, że byłby użyteczny w kodzie produkcyjnym jest użycie_end = object()
:-)Zerknij na to:
https://github.com/kmike/marisa-trie
Oto post na blogu od firmy, która z powodzeniem używa marisa trie:
https://www.repustate.com/blog/sharing-large-data-structure-across-processes-python/
Istnieje również kilka implementacji w czystym Pythonie, ale jeśli nie jesteś na ograniczonej platformie, chcesz użyć powyższej implementacji wspieranej przez C ++, aby uzyskać najlepszą wydajność:
źródło
Oto lista pakietów Pythona, które implementują Trie:
źródło
Zmodyfikowano z
senderle
metody (powyżej). Odkryłem, że Pythondefaultdict
jest idealny do tworzenia drzewa trie lub prefiksu.źródło
Nie ma „powinno”; to zależy od Ciebie. Różne implementacje będą miały różną charakterystykę wydajności, a ich wdrożenie, zrozumienie i poprawne wykonanie zajmie różną ilość czasu. Moim zdaniem jest to typowe dla rozwoju oprogramowania jako całości.
Prawdopodobnie najpierw spróbuję utworzyć globalną listę wszystkich dotychczas utworzonych węzłów trie i przedstawić wskaźniki potomne w każdym węźle jako listę indeksów na liście globalnej. Posiadanie słownika tylko po to, by przedstawiać linkowanie dziecka, wydaje mi się zbyt ciężkie.
źródło
Jeśli chcesz TRIE zaimplementowaną jako klasa Pythona, oto coś, co napisałem po przeczytaniu o nich:
źródło
Ta wersja używa rekurencji
Wynik:
źródło
Zdefiniuj Trie:
Utwórz próbę:
Wyszukaj:
Test:
źródło
True
tylko całe słowo, ale nie przedrostek, przy zmianie prefiksureturn '_end' in curr
nareturn True
Na zewnątrz
źródło
Klasa Pythona dla Trie
Trie Data Structure może być używana do przechowywania danych,
O(L)
gdzie L jest długością łańcucha, więc przy wstawianiu N łańcuchów złożoność czasowa byłaby taka,O(NL)
że ciąg można przeszukiwaćO(L)
tylko w ten sam sposób, co w przypadku usunięcia.Można sklonować z https://github.com/Parikshit22/pytrie.git
Code Oputpt
Prawda
Fałsz
[„minakshi”, „minhaj”]
7
minakshi
minhajsir
pari
parikshit
shubh
shubham
shubhi
źródło