Biorąc pod uwagę ogromną bazę dozwolonych słów (posortowane alfabetycznie) i słowo, znajdź słowo z bazy danych, która jest najbliższa podanemu słowu pod względem odległości Levenshteina.
Naiwnym podejściem jest oczywiście po prostu obliczenie odległości levenshteina między danym słowem a wszystkimi słowami w słowniku (możemy przeprowadzić wyszukiwanie binarne w bazie danych przed obliczeniem odległości).
Zastanawiam się, czy istnieje bardziej wydajne rozwiązanie tego problemu. Może jakaś heurystyka, która pozwala nam zmniejszyć liczbę słów do wyszukania lub optymalizację algorytmu odległości Levenshteina.
Linki do artykułów na ten temat są mile widziane.
źródło
Automaty Levenshtein: http://en.wikipedia.org/wiki/Levenshtein_automaton
Drzewa BK: http://en.wikipedia.org/wiki/BK-tree
źródło
Jeśli masz niewielką liczbę błędnych edycji, które będziesz tolerować, możesz spróbować użyć drzewa kropek . Oświadczenie: Napisałem ten papier, ale rozwiązuje to, czego chcesz: ma wysoki koszt miejsca na dysku, ale zapytania są naprawdę szybkie.
Ogólnie rzecz biorąc, lepiej spojrzeć na to odwrotnie: masz indeks wszystkich słów w słowniku. Teraz, jeśli słowo wejściowe w znajduje się w słowniku, przestań. W przeciwnym razie wygeneruj wszystkie warianty w odległości 1 i poszukaj ich. Jeśli ich tam nie ma, poszukaj odmian w odległości 2 itd.
Istnieje kilka ulepszeń tego podstawowego pomysłu.
źródło
źródło
Odpowiedziałem na bardzo podobne pytanie na cs.stackexchange.com ( /cs//a/2096/1490 ), a potem znalazłem to pytanie. Istnieje odpowiedź na przybliżone wyszukiwanie w sąsiedztwie w odległości edycji (tj. Algorytm generuje ciąg znaków, który jest w przybliżeniu tak blisko ciągu zapytania, jak najbliższy sąsiad ciągu zapytania). Piszę tutaj, ponieważ nie znajduję żadnego z odniesień, które tam podałem w podanych tutaj odpowiedziach.
źródło
Myślę, że to, czego chcesz, to algorytm Wagnera-Fischera: https://en.wikipedia.org/wiki/Wagner%E2%80%93Fischer_algorytm Kluczową sprawą jest to, że skoro słownik, przez który przechodzisz, jest posortowany, dwa kolejne słowa bardzo często mają długi prefiks, więc nie trzeba aktualizować całej macierzy dla każdego obliczenia odległości.
źródło
Możesz użyć Czy miałeś na myśli?
Następnie znajdź odległość Levenshteina między odpowiedzią zwróconą przez „Czy miałeś na myśli” a ciągiem wejściowym za pomocą programowania dynamicznego.
źródło
Did you mean?
funkcję. Poza tymDid you mean?
zwraca słowo, które jest bardzo bliskie podanemu wejściowi i robi to całkiem skutecznie. :)Jednym ze sposobów jest szkolenie modelu uczenia maszynowego do mapowania słów na wektory i mapowania odległości lewenshteina do odległości euklidesowej. Następnie możesz zbudować KDTree z wektorów dla słownika, którego chcesz użyć. Utworzyłem notatnik jupyter, który robi to tutaj: https://gist.github.com/MichaelSnowden/9b8b1e662c98c514d571f4d5c20c3a03
Zgodnie z komentarzami DW:
Podsumowanie struktury modelu:
Moje dane treningowe to tylko losowe ciągi, ale myślę, że wyniki mogłyby się naprawdę poprawić, gdyby dane treningowe były parami (literówka / poprawne słowo). Skończyło się na tym, że używałem,
/usr/share/dict/words
ponieważ jest powszechnie dostępny.źródło