搜索字母数组中的单词的算法

时间:2015-06-01 13:44:34

标签: java arrays algorithm search

所以我有一个数组,我必须搜索单词

数组:

        0   1   2   3   4   5   6   7   8   9   10  11
text    g   t   c   a   n   d   l   e   t   j   a   q

钥匙:

2 can
2 candle
3 a
3 an
3 and
6 let
10 a

该数字是从被搜索数组的开头开始的偏移量,该字符串是在该偏移量处找到的字典中的单词。请注意,多个单词可以从相同的偏移量开始,并且可以在多个位置找到相同的单词。另请注意,单词可以重叠。

这是我写的代码:

public ArrayList<Location> findWords(String[] dictionary, String text) {
    int keyLength = text.length();
    int dtLength = dictionary.length;

    ArrayList<Location> results;
    results = new ArrayList<>();

    for (int k = 0; k < keyLength; k++) {
        for (int d = 0; d < dtLength; d++) {
            if (dthasKey(dictionary[d], text, k)) {
                Location loc = new Location(k, dictionary[d]);
                results.add(loc);
            }
        }
    }
    return results;
}

private boolean dthasKey(String key, String text, int pos) {
    for (int i = 0; i < key.length(); i++) {
        if (key.length() >= text.length() - pos)
            return false;
        while (key.charAt(i) != text.charAt(pos + i)) {
            return false;
        }
    }
    return true;
}

我想知道是否有更好的解决方案来解决这个问题。如果你们这些人也可能提供最糟糕的时间复杂性,那就太棒了。我写的那个是:         O(k*n*m) 其中m是。的大小 字典,n是文本的大小,k是长度 最长的词。

2 个答案:

答案 0 :(得分:2)

问题的标准解决方案是使用Aho-Corasick string matching algorithm,它从字典中构建自动机,然后可以快速查找传递给它的字符串中的所有单词。 Google搜索揭示了许多Java实现。

构建自动机是O(n),其中n是字典所有单词中的字符数。但这是一次性成本。您可以使用该自动机在多个文档中搜索单词。

搜索单词的文件是O(m + z),其中m是文档中的字符数,z是找到的匹配数。

我不知道Aho-Corasick是否是最快的算法,但速度非常快。并且现有的Java实现将是一个很大的优势。但实施起来并不是特别困难。原始论文Efficient String Matching: an Aid to Bibliographic Search是非常易读的,虽然它可能需要在“点击”之前再次阅读,思考和阅读。并且伪代码示例足够详细,您可以将它们用作实现的基础。我为使用该文档作为我唯一参考的文章创建了C# implementation

答案 1 :(得分:0)

你可以为每个单词(只接受那个单词)创建一个自动机,然后同时在所有自动机中运行给定的文本,这将最终为O(m * k ^ 2 + n)