Пожалуйста, предложите умный статический алгоритм завершения слова - PullRequest
2 голосов
/ 06 ноября 2011

Это не домашняя работа; Я пытаюсь упростить и улучшить существующий неуклюжий графический интерфейс, написанный на C # / Winform / Sql Server 2008. Было бы здорово, если бы вы могли предложить что-то специфическое для этих технологий, но если бы вы могли указать мне на что-то еще, такое как Java / Решение MySql, тогда я тоже буду этому рад.

Был задан похожий вопрос, но вопрос / ответ был не таким продвинутым, как то, что я ищу: Учитывая список слов - какой будет хороший алгоритм для завершения слов в Java? Компромиссы: скорость / эффективность / объем памяти

Скажем, у меня есть таблица, содержащая информацию о книге: название, имя автора, описание. Я знаю, что все три не обязательно принадлежат к одной и той же таблице, но давайте предположим, что имеет смысл сделать это таким образом. Поэтому, когда пользователь вводит что-то (скажем, «Hari po») в текстовое поле / комбинированный список или в какой-либо пользовательский элемент управления, первое, что он должен получить в качестве первого предложения, - это, вероятно, «Гарри Поттер», соответствующее описание и автор. Для простоты давайте ограничимся поиском только по названию. Обратите внимание, что мне все равно, что «Хари» звучит как «Гарри» - приложение не нацелено на не носителей языка, но меня волнует тот факт, что «Хари по» находится всего в нескольких нажатиях клавиши «Гарри По». Итак, на ум приходит http://en.wikipedia.org/wiki/Levenshtein_distance, но это не совсем то, что мне нужно, потому что я хотел бы получить значимые результаты, как только я начну печатать (подумайте о предложении Google с другой целью). Мне нужен какой-то модифицированный алгоритм расстояния Левенштейна, который хорошо работает с частичным соответствием и не предполагает, что то, что я печатаю, должно быть в начале текста, который я пытаюсь сопоставить. Например, книга может называться «Как мальчик по имени Гарри Поттер влияет на наше общество», и я хочу, чтобы этот заголовок всплыл в поиске, однако я бы хотел увидеть что-то вроде «Гарри Поттер и Орден «Феникс» поднимаются наверх, потому что мой запрос начинается с этого.

Я мог бы несколько раз попробовать расстояние Левенштейна для всех возможных подстрок с длиной запроса +/- 2, а затем как-то взвесить их, где в строке появляется подстрока «сортировать», а затем выбрать максимальное значение. коэффициент совпадения. Моя первая задача - сделать это неэффективно. Во-вторых, должен быть способ получить лучшие результаты, даже если скорость не была проблемой. В-третьих, кто-то наверняка делал нечто подобное раньше, так зачем изобретать велосипед?

Количество уникальных строк в базе данных будет составлять до 20 000. То, что мне нужно, это что-то вроде предложения поиска Google или Visual Studio 2010 IntelliSense (автозаполнение кода), за исключением того, что он не должен пытаться вспомнить, что пользователь вводил в прошлом, и корректировать предложение, основываясь на этом. Нет необходимости выполнять расширение запроса; просто работаю с актуальным контентом. С точки зрения пользователя он должен работать аналогично поиску в Google и IntelliSense, например, он должен придумать ряд ранжированных вариантов, а также придумать разумный способ сократить этот список в нужной точке (например, если на самом деле ничего не соответствует запросу, то ничего не предлагайте, а не показывайте лучшее из худших совпадений) , а также, если первые несколько результатов имеют сильный рейтинг, но последующие имеют гораздо более слабый результат относительно лучших результатов, то, возможно, скрыть слабые.

Возможно, вам известен инструмент / библиотека с открытым исходным кодом разумного размера с открытым и читабельным исходным кодом, из которого я могу получить идеи?

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

Пожалуйста, задавайте уточняющие вопросы, если что-то не понятно о том, что я делаю.

Ответы [ 4 ]

1 голос
/ 08 ноября 2011

Если вы наберете "hari po" в Google, предложения в верхней части будут правильно "Гарри Поттер" Google делает это, используя "чертовски крутой алгоритм" . Вы недалеки от расстояния редактирования Левенштейна : Google использует BK-деревья IIRC.

Насколько я понимаю, это в основном дерево, построенное из Левенштейна Править Расстояние .

Возможно, на данный момент доступно несколько работ по этому вопросу. Впервые я прочитал об этом несколько лет назад в блоге под названием «Черт крутые алгоритмы» :

http://blog.notdot.net/2007/4/Damn-Cool-Algorithms-Part-1-BK-Trees

Но вы должны знать, что, хотя Levenhstein Edit Distance тривиально (его можно реализовать примерно в 20 строках кода), bk-дерево кажется совершенно другим зверем для разработки .. .

1 голос
/ 06 ноября 2011

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

0 голосов
/ 06 ноября 2011

Для простого алгоритма завершения вы можете объединить индекс KWIC с основанием дерева.

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

Затем строите радикальное дерево поверхСтроки, такие, что когда вы вводите «Гарри», вы найдете все возможные следующие слова после «Гарри».

Хотя это может звучать так, как будто это действительно взорвет размер вашей БД, на самом деле этотолько примерно вдвое, в зависимости от того, как вы выбираете "значимые" начальные точки.(Основное дерево несколько более компактно, чем хранение каждой строки отдельно, в дополнение к созданию эффективных поисков.)

0 голосов
/ 06 ноября 2011

Может быть, вы хотите поискать триграмм? Поиск по триграмме должен создать все возможности из 3-х букв ввода и искать похожие строки в совпадении http://en.wikipedia.org/wiki/Trigram

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