如何检查字符串的排列(或部分)是否在列表(字典)中?

时间:2016-04-24 13:15:22

标签: javascript algorithm

我为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万字还有多长时间......有更好的方法吗?

2 个答案:

答案 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并搜索这些单词。确定最小字长和最大字长,然后创建该长度的窗口。这需要创建排列,此时你会进入更有趣的算法,如搜索树,反向跟踪等。我建议阅读相关的维基百科文章。