Адресная книга и структура trie

У меня к тебе есть вопрос. Мне нужно реализовать бизнес-адресную книгу, содержащую 30000 имен. Все имена содержат имя и фамилию. Мне нужно реализовать текстовое поле автозаполнения, которое выполняет поиск не только по имени, но и по фамилии. При поиске в google я видел, что эта проблема решается с помощью patricia trie, но он выполняет только поиск по префиксу, поэтому, если я создаю trie с именем + фамилией, как я могу искать не только по имени, но и по фамилии?

Должен ли я дублировать записи, вставляя две строки, подобные этой? Имя+фамилия и Фамилия+имя

Пожалуйста помогите!!!

Поиск должен быть очень эффективным.

Спасибо.


person Mapo    schedule 06.06.2012    source источник


Ответы (2)


Другая возможность — создание двух попыток.

Первый (пусть будет T1) для имен, а второй (пусть T2) для фамилий.

При построении дерева из каждого терминатора слова в T1 (обычно обозначаемого знаком $) добавьте список указателей на соответствующие записи в T2 и наоборот.

т.е. если John Doe является основным блюдом:

T1:
     J
     |
     O
     |
     H
     |
     N
     |
     $1
T2:
     D
     |
     O
     |
     E
     |
     $2

$1 будет содержать список, содержащий указатель на $2, а $2 будет содержать список, содержащий $1.

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

Поиск полного имени выполняется путем поиска в обеих попытках (ищите имя в T1 и фамилию в T2 и получаете соответствующие $1 и $2 соответственно), затем вам нужно проверить, совпадают ли указатели (список l1 в $1 содержит $2, а список l2 в $2 содержит $1). Если да - имя в словаре.

Обратите внимание, что когда у вас есть указатель на узел $, можно просто вернуться к дереву, пока вы не доберетесь до корня, чтобы получить слово, которое представляет этот знак $. (требуется указатель на родителя от каждого узла)

Также обратите внимание: я объяснил о простых попытках, но на самом деле нет причин, почему бы не использовать вместо этого попытки patricia, используя тот же подход.

person amit    schedule 06.06.2012
comment
Хорошо, спасибо за ваш ответ. Я должен изучить это. Один вопрос. Поиск по двум разным попыткам эффективен? Как насчет производительности? Учтите, что эта структура должна быть реализована на стороне сервера! Спасибо - person Mapo; 07.06.2012
comment
@ user788779: Поиск в двух попытках не менее эффективен, чем поиск в одной, в этом случае он может быть даже лучше, потому что его можно распараллелить, что может быть полезно для огромных строк (хотя это редко бывает). Единственное замедление в этом подходе — сопоставление списка указателей после того, как вы нашли $1 и $2. - person amit; 07.06.2012
comment
В порядке. Я читал, что возможным решением может быть использование индекса permuterm для поиска по подстановочным знакам. По-вашему, это решение могло бы мне помочь? - person Mapo; 07.06.2012
comment
@user788779: user788779: Я думаю, это может вам помочь, но учтите, что при таком подходе потребуется вдвое больше места. Я думаю, что потребление времени одинаково для обоих подходов. - person amit; 07.06.2012
comment
Я бы не слишком беспокоился о поиске идеального решения — у вас все будет хорошо, если оно эффективно. - person Stefan Haustein; 07.06.2012
comment
@all: у меня есть идея. Не могли бы вы сказать мне, если это действительно? Я создаю тройку, состоящую из имени+фамилии;идентификатор_пользователя и фамилию+имя;идентификатор_пользователя При автозаполнении, чтобы показать только одну запись на человека, я могу контролировать, существует ли этот идентификатор пользователя и не показывать его. Может ли это работать? - person Mapo; 07.06.2012
comment
@ user788779: Проблема с этим подходом: если вы введете "Joh", автозаполнение обнаружит, что это может относиться к "John", но не сможет связать его с "Doe", поскольку вы не можете искать по идентификатору в предлагаемой структуре данных. - person amit; 07.06.2012
comment
Хорошо, но если я буду искать Доу, я найду Доу Джона! - person Mapo; 07.06.2012
comment
Но если есть сущность с именем Марко Марчи. Если я буду искать marc, я найду два результата marco marchi и marchi marco, но на стороне клиента я покажу только один из них, потому что у меня есть идентификатор. Это правильно? Можно ли использовать этот подход? Это эффективно? - person Mapo; 07.06.2012

Да, самое простое решение - вставить оба варианта. Однако это должно дублировать только строку поиска, а не запись. Вы, вероятно, захотите каким-то образом нормализовать разделение между именем и фамилией (= удалить знаки препинания для адресной книги и для пользовательского ввода), чтобы вы могли найти записи во всех случаях для ввода, например «Джон Доу», «Доу». , Джон», «Доу Джон» и т. д.

Я бы не использовал частичное дерево, а просто сбалансированное дерево. Во многих языках вы найдете сбалансированные деревья как реализацию отсортированной карты в библиотеке (по крайней мере, Java и C++).

person Stefan Haustein    schedule 06.06.2012
comment
Спасибо за ответ!! Но когда я ищу строку, можно получить две записи, представляющие одного и того же человека! Например, Марко Марчи. Поэтому, если я ищу marc, я получаю две записи: marco Marchi и Marchi Marco. Так что делать? - person Mapo; 07.06.2012
comment
Как сбалансированное дерево может дать ему частичное совпадение? Также обратите внимание, что сбалансированные деревья менее эффективны - асимптотически говоря, для поиска существования строк. - person amit; 07.06.2012
comment
Вы также можете добавить к ключу части адреса или даты рождения, в идеале что-то, что поможет пользователю выбрать правильную запись. Чтобы убедиться, что у вас есть уникальный ключ и вам не нужен список в качестве значения, также добавьте уникальный идентификатор записи. Вы можете скрыть идентификатор от пользователя. - person Stefan Haustein; 07.06.2012
comment
@amit: чтобы получить частичное совпадение в дереве, начните перебирать ключи с префиксом, пока не найдете запись, которая не соответствует префиксу. Теоретически попытки могут иметь лучшую производительность, но есть причина, по которой большинство стандартных библиотек не имеют их: потребление памяти ужасно, и структура данных будет разбросана по огромной области памяти, вызывая проблемы с кешем процессора. - person Stefan Haustein; 07.06.2012
comment
Сбалансированное дерево против Патриции Три? Что лучше для моей проблемы? Спасибо - person Mapo; 07.06.2012
comment
@ user788779: Очень сложно сказать, вам, вероятно, придется сравнить оба в конкретной системе, чтобы получить четкое заключение. - person amit; 07.06.2012
comment
Если только вы не цените время реализации :) - person Stefan Haustein; 07.06.2012