Scrabble word finder: создание trie, хранение trie, использование trie?

что я пытаюсь сделать:

  • создайте мобильное веб-приложение, где пользователь может получить помощь в поиске слов для игры при игре в scrabble
  • пользователи получают предложения word, введя любое количество букв и 0 или более подстановочных знаков

Как я пытаюсь сделать это:

  • использование базы данных MySQL со словарем, содержащим более 400k слов
  • использование ASP.NET с C# в качестве сервера язык программирования
  • использование HTML5, CSS и Javascript

мой текущий план:

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

имея план не хорошо, если вы не можете его выполнить, это то, что мне нужна помощь:

  • как построить Trie из базы данных? (ОБНОВЛЕНИЕ: I хотите создать Trie, используя слова уже в моей базе данных, после этого я больше не буду использовать базу данных для сопоставления слов)
  • как хранить Trie для быстрого и легкого доступа? (Обновление: поэтому я могу выбросить свою базу данных)
  • как использовать C# для поиска слов с помощью Trie в зависимости от букв и подстановочных знаков?

и наконец:
Любая помощь очень ценится, я все еще новичок с C# и MySQL, поэтому, пожалуйста, будьте нежный

Спасибо большое!

1 ответов


во-первых, давайте рассмотрим ограничения на проблему. Вы хотите сохранить список слов для игры в структуре данных, которая эффективно поддерживает проблему "анаграмма". То есть, учитывая "стойку" из n букв, каковы все N-или-менее-буквенные слова в списке слов, которые могут быть сделаны из этой стойки. список слов будет около 400K слов, и поэтому, вероятно,от одного до десяти мегабайт строковых данных при несжатом.

trie-классическая структура данных, используемая для решения этой проблемы проблема, потому что она сочетает в себе как эффективность памяти с эффективностью поиска. С помощью списка слов около 400K слов разумной длины вы сможете сохранить trie в памяти. (В отличие от решения типа b-tree, где вы держите большую часть дерева на диске, потому что оно слишком велико, чтобы поместиться в памяти сразу.)

trie в основном не более чем 26-арное дерево (при условии, что вы используете Римский алфавит) , где каждый узел имеет букву и один дополнительный бит на каждом узел, который говорит, является ли это конец слова.

Итак, давайте набросаем структуру данных:

class TrieNode
{
    char Letter;
    bool IsEndOfWord;
    List<TrieNode> children; 
}

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

вы можете начать с пустой бор:

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

то есть это" корневой " узел trie, который представляет собой начало слова.

как вы добавляете слово "AA", первое слово в словаре Scrabble? Ну, сначала сделайте узел для первой буквы:

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

хорошо, наш trie теперь

^
|
A

теперь добавьте узел для второй буквы:

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

наш trie теперь

^
|
A
|
A$   -- we notate the end of word flag with $

большой. Теперь предположим, что мы хотим добавить AB. У нас уже есть узел для "A", поэтому добавьте к нему узел" B$":

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

и теперь у нас есть

    ^
    |
    A
   / \
  A$   B$

продолжай в том же духе. Конечно, вместо того, чтобы писать "корень.Дети[0]..."вы напишете цикл, который ищет trie, чтобы увидеть, существует ли узел, который вы хотите, а если нет, создайте его.

чтобы сохранить ваш trie на диске-честно говоря, я бы просто сохранил список слов в виде текстового файла и восстановите trie, когда вам нужно. Это не должно занять более 30 секунд или около того, а затем вы можете повторно использовать Боре в памяти. Если вы хотите сохранить trie в каком-то формате, который больше похож на trie, не должно быть сложно придумать формат сериализации.

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

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