Mysql
 sql >> база данни >  >> RDS >> Mysql

Търсачката на думи Scrabble:изграждане на trie, съхраняване на trie, използване на trie?

Първо, нека разгледаме ограниченията на проблема. Искате да съхраните списък с думи за игра в структура от данни, която ефективно поддържа проблема "анаграма". Тоест, като се има предвид „рафт“ от n букви, какви са всички думи с n или по-малко букви в списъка с думи, които могат да бъдат направени от този багажник. списъкът с думи ще бъде около 400 000 думи и вероятно е около един до десет мегабайта низови данни, когато е некомпресиран.

Trie е класическата структура от данни, използвана за решаване на този проблем, тъй като съчетава ефективността на паметта и ефективността на търсенето. Със списък с думи от около 400 000 думи с разумна дължина би трябвало да можете да запазите опита в паметта. (За разлика от решението от типа b-дърво, при което държите по-голямата част от дървото на диск, защото е твърде голямо, за да се побере в паметта наведнъж.)

Опитът по същество не е нищо повече от 26-арично дърво (ако приемем, че използвате латинската азбука), където всеки възел има буква и един допълнителен бит на всеки възел, който казва дали това е краят на думата.

Така че нека скицираме структурата на данните:

class TrieNode{ char Letter; bool IsEndOfWord; List деца; } 

Това разбира се е само скица; вероятно бихте искали да ги направите да имат подходящи средства за достъп и конструктори и какво ли още не. Също така, може би плоският списък не е най-добрата структура от данни; може би някакъв речник е по-добър. Моят съвет е първо да го накарате да работи и след това да измерите неговата производителност и ако е неприемливо, тогава експериментирайте с извършване на промени, за да подобрите неговата производителност.

Можете да започнете с празен опит:

TrieNode root =new TrieNode('^', false, new List()); 

Тоест, това е "корен" възел на trie, който представлява началото на дума.

Как добавяте думата "AA", първата дума в речника на Scrabble? Е, първо направете възел за първата буква:

root.Children.Add('A', false, new List()); 

Добре, нашият опит е сега

^|A 

Сега добавете възел за втората буква:

root.Children[0].Children.Add(new trieNode('A', true, new List())); 

Нашият опит е сега

^|A|A$ -- отбелязваме края на флага на думата с $ 

Страхотен. Сега да предположим, че искаме да добавим AB. Вече имаме възел за "A", така че добавете към него възел "B$":

root.Children[0].Children.Add(new trieNode('B', true, new List()); 

и сега имаме

<предварителен код> ^ | A / \ A$ B$

Продължавай така. Разбира се, вместо да пишете „root.Children[0]...“, вие ще напишете цикъл, който търси опита, за да види дали желаният възел съществува, и ако не, създайте го.

За да съхраня вашия опит на диск - честно казано, просто бих съхранил списъка с думи като обикновен текстов файл и бих възстановил опита, когато имате нужда. Това не трябва да отнеме повече от 30 секунди и след това можете да използвате повторно опита в паметта. Ако искате да съхраните trie в някакъв формат, който прилича повече на trie, не би трябвало да е трудно да излезете с формат за сериализиране.

За да търсите в опита за съвпадение на багажник, идеята е да проучите всяка част от опита, но да отрежете областите, където багажникът не може да съвпадне. Ако нямате никакви "А" на багажника, няма нужда да слизате надолу по който и да е "А" възел. Очертах алгоритъма за търсене в предишния ви въпрос.

Имам реализация на постоянен опит във функционален стил, за който имах намерение да пиша в блог от известно време, но така и не стигнах до него. Ако евентуално го публикувам, ще актуализирам този въпрос.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. ColdFusion - Вмъкване на арабски/персийски знаци в mysql

  2. Управление на MySQL база данни в cPanel с PHPMyAdmin

  3. групово вмъкване на списъчни стойности с SQLAlchemy Core

  4. Не мога да накарам заявката за източник на MySQL да работи с помощта на Python mysqldb модул

  5. Sequelize bulkCreate() връща стойност NULL за първичен ключ