Требуемый алгоритм: найти все слова словаря, которые похожи на слова в свободном тексте - PullRequest
15 голосов
/ 02 ноября 2009

У нас есть список из около 150 000 слов, и когда пользователь вводит свободный текст, система должна представить список слов из словаря, которые очень близки к словам в свободном тексте.

Например, пользователь вводит: «Я хотел бы купить игрушки legoe в Walmart». Если словарь содержит «Lego», «Car» и «Walmart», система должна представить «Lego» и «Walmart» в списке. «Walmart» очевиден, потому что он идентичен слову в предложении, но «Lego» достаточно похож на «Legoe», чтобы упомянуть также. Однако ничто не похоже на «Автомобиль», так что это слово не отображается.

Отображение списка должно осуществляться в режиме реального времени. Это означает, что когда пользователь ввел предложение, список слов должен присутствовать на экране. Кто-нибудь знает хороший алгоритм для этого?

Словарь фактически содержит понятия, которые могут включать пробел. Например, «Космический корабль Лего». Идеальное решение также распознает эти многословные понятия.

Любые предложения приветствуются.

Ответы [ 4 ]

9 голосов
/ 02 ноября 2009

Взгляните на http://norvig.com/spell-correct.html для простого алгоритма. В статье используется Python, но в конце есть ссылки на реализации на других языках.

7 голосов
/ 02 ноября 2009

Вы будете делать несколько поисков слов по фиксированному словарю. Поэтому вам нужно подготовить свой словарь. По логике вещей, вы можете быстро исключить кандидатов, которые «просто слишком разные».

Например, слова car и dissimilar могут иметь общий суффикс, но они очевидно не являются орфографическими ошибками друг друга. Теперь, почему это так очевидно для нас, людей? Для начала длина совсем другая. Это немедленная дисквалификация (но с одним исключением - ниже). Итак, ваш словарь должен быть отсортирован по длине слова. Сопоставьте введенное слово со словами одинаковой длины. Для коротких слов это означает +/- 1 символ; более длинные слова должны иметь больший запас (насколько точно ваше демографическое заклинание?)

Как только вы ограничите себя кандидатами в слова одинаковой длины, вы захотите удалить слова, которые совершенно не похожи друг на друга. Под этим я подразумеваю, что они используют совершенно разные буквы. Это проще всего сравнить, если отсортировать буквы в слове по алфавиту. Например. car становится "acr"; rack становится "ackr". Вы будете делать это при предварительной обработке для вашего словаря и для каждого входного слова. Причина в том, что дешево определить (размер) разницу двух отсортированных наборов. (Добавить комментарий, если вам нужно объяснение). car и rack имеют разницу в размере 1, car и hat имеют разницу в размере 2. Это еще больше сужает набор кандидатов. Обратите внимание, что для более длинных слов вы можете выручить рано, когда вы нашли слишком много различий. Например. dissimilar и biography имеют общую разницу в 13, но, учитывая длину (8/9), вы, вероятно, сможете выручить, когда найдете 5 отличий.

Это оставляет вам набор слов-кандидатов, которые используют почти одинаковые буквы, а также имеют практически одинаковую длину. С этого момента вы можете начать использовать более совершенные алгоритмы; вам больше не нужно выполнять 150 000 сравнений для каждого входного слова.

Теперь, для исключения длины, упомянутого ранее: проблема в «словах», подобных greencar. Это не совсем соответствует слову длины 8, но для людей совершенно очевидно, что это значит. В этом случае вы не можете по-настоящему разбить входное слово на любой случайной границе и выполнить дополнительные неточные совпадения N-1 для обеих половин. Однако выполнимо проверить только пропущенное место. Просто найдите все возможные префиксы. Это эффективно, потому что вы будете использовать одну и ту же часть словаря снова и снова, например, g gr, gre, gree и т. Д. Для каждого найденного префикса проверьте, есть ли оставшийся суффикс в словаре, например, reencar, eencar. Если обе части входного слова есть в словаре, а само слово - нет, можно предположить пропущенный пробел.

5 голосов
/ 02 ноября 2009

Вы, вероятно, захотите использовать алгоритм, который вычисляет расстояние Левенштейна .

Однако, поскольку ваш набор данных довольно большой и вы будете сравнивать множество слов с ним, прямая реализация типичных алгоритмов , которые делают это, не будет практичной.

Чтобы найти слова за разумное время, вам нужно будет каким-то образом проиндексировать ваш набор слов, что облегчит нечеткое сопоставление строк .

Одним из таких способов индексирования будет использование дерева суффиксов . Другой подход заключается в использовании н-граммов .

Я бы склонялся к использованию дерева суффиксов, так как мне легче было обернуть вокруг него голову, и я считаю, что оно больше подходит для этой проблемы.

1 голос
/ 02 ноября 2009

Может быть интересно взглянуть на некоторые алгоритмы, такие как расстояние Левенштейна , которое может вычислить величину разности между 2 строками.

Я не уверен, на каком языке вы думаете, но PHP имеет функцию с именем levenshtein, которая выполняет это вычисление и возвращает расстояние. Также есть функция с именем similar_text, которая выполняет аналогичные функции. Здесь приведен пример кода для функции levenshtein, которая проверяет слово по словарю возможных слов и возвращает самые близкие слова.

Надеюсь, это даст вам некоторое представление о том, как может работать решение!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...