У меня есть словарь от 50K до 100K строк (может быть до 50 + символов), и я пытаюсь найти, является ли данная строка в словаре с некоторыми "edit «Допуск расстояния. (Например, Левенштейн). Перед выполнением поиска я отлично разбираюсь в какой-либо структуре данных.Быстрый нечеткий/приблизительный поиск в словаре строк в Ruby
Моя цель - запустить тысячи строк против этого словаря как можно быстрее и вернуть ближайшего соседа. Я был бы в порядке, просто получая логическое значение, которое скажет, присутствует ли данное значение в словаре или нет, если есть значительно более быстрый алгоритм для этого
Для этого я сначала попытался вычислить все расстояния Левенштейна и взять минимум и это было явно ужасно медленно. Так что я попытался реализовать Левенштейн TRIE на основе этой статьи http://stevehanov.ca/blog/index.php?id=114
Смотрите мою суть здесь для воспроизведения теста: https://gist.github.com/nicolasmeunier/7493947
Вот несколько тестов, которые я получил на моей машине:
Редактировать расстояние 0 (идеальный матч)
Benchmark.measure { 10.times { dictionary.search(random_word, 0) } }
<Benchmark::Tms:0x007fa59bad8908 @label="", @real=0.010889, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.00999999999999801, @total=0.00999999999999801>
* Изменить расстояние 2, она становится намного медленнее *
Benchmark.measure { 10.times { dictionary.search(random_word, 2) } }
<Benchmark::Tms:0x007fa58c9ca778 @label="", @real=3.404604, @cstime=0.0, @cutime=0.0, @stime=0.020000000000000018, @utime=3.3900000000000006, @total=3.4100000000000006>
И спускается оттуда и стать чрезвычайно медленным для редактирования расстояния больше, чем 2 (1+ секунду в среднем на тестируемой строки).
Я хотел бы знать, как/если бы я мог значительно ускорить это. Если существуют уже существующие решения в рубинах/драгоценных камнях, я также не хочу изобретать колесо ...
EDIT 1: В моем случае я ожидаю, что большинство строк, которые я сопоставляю со словарем NOT, быть там. Поэтому, если есть какой-либо алгоритм для быстрого удаления строки, это может реально помочь.
Спасибо, Николя
Николас, я не решается комментировать, потому что я не знаком с литературой и не хочу отвлечься от обсуждения, но мне напомнили о проблеме, с которой у меня было много лет назад, определения того, был ли файл идентичен любому файлу в большой «библиотеке» на удаленном компьютере. Я проиндексировал файлы по «сигнатуре файла», подпись была результатом вычисления CRC (циклической проверки избыточности) (Fixnum, но я не помню, сколько байтов). Это было очень быстро и на 100% точно. Идея заключалась бы в том, чтобы вычислить подпись для каждой строки, а затем посмотреть, что в индексе. –
Вы ищете 100% идентичные файлы или это допустимо для любого предела погрешности? Это то, что вы могли бы контролировать? Я посмотрю на это больше. Спасибо за предложение. –
Вы попробовали [это] (https://github.com/kiyoka/fuzzy-string-match) и [это] (https://github.com/seamusabshere/fuzzy_match)? – mdesantis