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, но обрезать области, где стойка не может совпадать. Если у вас нет никаких "а"на стойке, нет необходимости спускаться любой узел "а". Я набросал алгоритм поиска в вашем предыдущем вопросе.
у меня есть реализация функционального стиля, о котором я собирался писать в блоге некоторое время, но так и не дошел до него. Если я в конечном итоге опубликую это, я обновлю этот вопрос.