存储单词列表的有效结构是前缀树 https://en.wikipedia.org/wiki/Trie。例如,给定一个像这样的字典
'car',
'card',
'carder',
'care',
'cared',
'cares',
'caring',
'can'
特里树可能看起来像这样
(where 0
表示单词的结尾)。
构建 trie 的代码相当简单:
function buildTree(words) {
var tree = {};
words.forEach(function (word) {
var t = tree;
[].forEach.call(word + "0", function (char) {
t = t[char] || (t[char] = {});
});
});
return tree;
}
现在,要枚举以给定前缀开头的所有单词,只需递归遍历 trie 并收集匹配的单词:
function findWords(prefix, tree) {
var found = [];
function walk(pfx, t, word) {
if (!pfx) {
if (t[0])
found.push(word)
for (var c in t)
walk("", t[c], word + c);
} else if (pfx[0] in t)
walk(pfx.substr(1), t[pfx[0]], word + pfx[0]);
}
walk(prefix, tree, "");
return found;
}
完整代码:
function buildTree(words) {
var tree = {};
words.forEach(function (word) {
var t = tree;
[].forEach.call(word + "0", function (char) {
t = t[char] || (t[char] = {});
});
});
return tree;
}
function findWords(prefix, tree) {
var found = [];
function walk(pfx, t, word) {
if (!pfx) {
if (t[0])
found.push(word)
for (var c in t)
walk("", t[c], word + c);
} else if (pfx[0] in t)
walk(pfx.substr(1), t[pfx[0]], word + pfx[0]);
}
walk(prefix, tree, "");
return found;
}
words = [
'car',
'card',
'carder',
'care',
'cared',
'cares',
'caring',
'can'
]
prefixTree = buildTree(words);
document.write(findWords("care", prefixTree));
要删除以另一个单词开头的单词,您可以按照上面的方式构建 trie,然后遍历它,在终止标记后剪切一次搜索(0
)发现:
function buildTree(words) {
var tree = {};
words.forEach(function (word) {
var t = tree;
[].forEach.call(word + "0", function (char) {
t = t[char] || (t[char] = {});
});
});
return tree;
}
function findShortWords(tree) {
var found = [];
function walk(t, word) {
if(t[0]) {
found.push(word);
return;
}
for (var c in t)
walk(t[c], word + c);
}
walk(tree, "");
return found;
}
words = [
'card',
'carder',
'care',
'cared',
'cares',
'caring',
'can',
'canoe',
'bald',
'balder',
'balding',
'foo'
]
prefixTree = buildTree(words);
document.write(findShortWords(prefixTree));