问题描述
我正在为英语词典中的每个单词创建一个Trie
结构。我想将此结构用于单词搜索和拼字游戏等游戏,但我不知道在运行时生成该结构的速度是否更快,或者是否应该设法将这种Trie
结构扁平化为{ {1}}或JSON
在运行时读入内存。
我对创建数据库或存储数据以供以后使用并不了解,因此任何建议都很棒-现在我正在查看XML
和Jackson
。最终目标是将该应用程序移植到我的网站上的Java
。
解决方法
仅通过Java
,就可以生成Trie结构并在您的网站上使用它,而无需使用JavaScript
。 Trie
和insert
这两种方法的简单search
结构在JS
中看起来像这样:
function Trie() {
this.root = new TrieNode();
this.insert = function(key) {
let length = key.length,next = this.root;
for (let level = 0; level < length; level++) {
let character = key.charAt(level);
if (next.children[character] == null) {
next.children[character] = new TrieNode();
}
next = next.children[character];
}
next.endOfWord = true;
}
this.search = function(key) {
let length = key.length,next = this.root;
for (let level = 0; level < length; level++) {
let character = key.charAt(level);
if (next && next.children[character]) {
next = next.children[character];
continue;
}
return false;
}
return next && next.endOfWord;
}
}
function TrieNode() {
this.children = {};
this.endOfWord = false;
}
使用上面的简单实现,您可以创建Trie
实例并插入所需的所有单词:
const trie = new Trie();
trie.insert("hello");
trie.insert("hi");
trie.insert("help");
trie.insert("helpful");
... more words
例如,使用Node.js,您可以:
- 从源文件中读取所有必需的单词。
- 对于每个单词,请使用
trie
方法将其插入insert
结构中。 - 通过
JSON
从对象生成JSON.stringify(trie)
。 - 将其保存到文件
trie.js
中,以后可以在您的页面上使用。
上述单词的结果js
文件应类似于:
{
"root":{
"children":{
"h":{
"children":{
"e":{
"children":{
"l":{
"children":{
"l":{
"children":{
"o":{
"children":{
},"endOfWord":true
}
},"endOfWord":false
},"p":{
"children":{
"f":{
"children":{
"u":{
"children":{
"l":{
"children":{
},"endOfWord":true
}
},"endOfWord":false
}
},"endOfWord":false
}
},"endOfWord":true
}
},"endOfWord":false
}
},"endOfWord":false
},"i":{
"children":{
},"endOfWord":true
}
},"endOfWord":false
}
},"endOfWord":false
}
}
要使用代码创建有效的JS
文件,您需要在开头添加:const RAW_TRIE =
字符串,因此我们的文件如下所示:
const RAW_TRIE = {
"root":{
"children":{
"h":{
...
您创建了一个原始Trie
对象,可以通过将以下行添加到HTML
或模板文件中来将该对象包含在页面中:
<script src="www.your-domain.com/path/to/static/file/trie.js"></script>
由于已加载此文件,因此您应该有权访问RAW_TRIE
对象。您可以将prototype设置为Trie
并使用搜索方法:
const TRIE = Object.setPrototypeOf(RAW_TRIE,new Trie());
console.log("hello exists: " + TRIE.search("hello"));
console.log("hello1 does not exist: " + TRIE.search("hello1"));
这种方法允许您在服务器端创建需要的所有单词的文件,客户端可以下载该文件并将其用作常规静态文件。
,注意:以上解决方案是实现此目的的唯一方法,可以改进或更改某些(或全部)步骤。它不是最终版本 可以在不改变生产的情况下使用。您可以尝试 对其进行优化,并通过更改来使
trie.js
文件尽可能小TrieNode
功能,甚至将其删除。
在这里,您可以通过扩展原生Map
原型来创建Trie:
class TrieNode extends Map {
add(word) {
if (!word.length) return super.set("end",true);
let child = this.get(word[0]);
if (!child) this.set(word[0],child = new TrieNode);
child.add(word.slice(1));
return this; // optional: to allow chaining
}
has(word) {
if (!word.length) return super.has("end");
let child = this.get(word[0]);
return !!child && child.has(word.slice(1));
}
* [Symbol.iterator]() {
for (let [letter,child] of super.entries()) {
if (letter === "end") yield ""
else for (let word of child) yield letter + word;
}
}
}
// Demo
let trie = new TrieNode;
// Insert all words
for (let word of ["so","some","somebody","someone","something","son"]) {
trie.add(word);
}
// For a series of strings,check whether they are in the Trie
for (let word of Array.from("somethings",(_,i) => "somethings".slice(0,i))) {
console.log(`"${word}" => ${trie.has(word)}`);
}
// List all words that are in the Trie
for (let word of trie) console.log(word);