我为Scrabble编写了一个简单的搜索应用程序。从字符串中查找所有可能的单词。 排列部分完成。我创建了一个函数Permute(string),它输出一个包含所有排列的数组。
var dictionary=["abc","abcd",ab","dhgd","adbft"];
var input="abcd";
output=Permute(input);
//result:
0:"abcd"
1:"abdc"
2:"acbd"
3:"acdb"
4:"adbc"
5:"adcb"
...etc
现在,我必须检查单词是否存在。我应该尝试所有长度吗?还有另一种更有效的方法吗?
//Check all the item of the output array
for(var i=0; i<output.length;i++){
//Check if all length of output
for(var j=2;j<output[i].length;i++)
//Check all these possibilities if they exist in the dictionary
for(word in dictionary){
output[i].substring[1:j]==dictionary[word];
}
}};
我无法想象如果字典是25万字还有多长时间......有更好的方法吗?
答案 0 :(得分:4)
您不需要生成所有排列。相反,在一个字母的排列上将您的密钥设为字典。词汇最小的permuation是最简单的 - 只需对键中的字母进行排序。
因此,您的字典将成为从排序的字母串到该字符串的字谜的地图,这些字母是实际的单词。例如,如果'god'
和'dog'
是单词,那么您的词典将会有一个条目'dgo' -> ['dog','god']
。
然后,要进行搜索,只需对输入中的所有字母进行排序,然后检查字典中是否有结果字符串的所有子序列。
如果您有'ogdb'
,则排序会生成'bdgo'
,并检查字典'b'
,'d'
,'g'
,'o'
,'bd'
,'bg'
,'bo'
等。当您到达'dgo'
时,您会在'god'
和'dog'
中找到connect()
字典。
有7个字母,有127个可能的子序列。检查127键的字典非常快。
答案 1 :(得分:2)
用anagrams检查的第一件事是长度。如果你的词典仅用于检查排列是否存在,那么我将创建一个长度为第一维的结构。例如
dictionary = {1: ['a', 'i'], ... 3: ['cat', 'dog', 'too']}
这很容易做到。
接下来,排列不是检查字谜的最有效方法。例如,您可以对字符进行排序,然后将它们进行比较:
dictionary = {1: ['a', 'i'], ... 3: ['act', 'dgo', 'oot']}
然后,您可以对查询字符串中的字符进行排序并进行直接比较。这减少了很大一部分排列。
然后你应该重新考虑使用字典的线性结构。基于哈希的东西效果更好。为什么不在Javascript中使用内置字典。
dictionary = {1: {'a': ['a'], 'i': ['i']}, ... 3: {'act': ['cat', 'cat'], 'dgo': ['dog'], 'oot': ['too']}}
这会将已排序的字符串映射到可能的字符串字符串。
然后找到你可能的单词,你只需查看dictionary[myword.length][sort_string(myword)]
您的排序功能是:
function sort_string(input) {
return input.split("").sort().join("")}
由此产生的复杂性将是O(1)ish(计算长度的一步,对字母进行排序的一步,查找第一级的一步,哈希和查找第二级的一步)。随着字典的增加,它不会减慢。
您的原文是O(n),即在字典中搜索存在的字数,速度取决于字典的大小。
如果您想搜索可能的可用单词,那么您将要创建ngrams并搜索这些单词。确定最小字长和最大字长,然后创建该长度的窗口。这需要创建排列,此时你会进入更有趣的算法,如搜索树,反向跟踪等。我建议阅读相关的维基百科文章。