如何有效地将整个英语词典添加到trie数据结构中

时间:2013-06-02 16:15:52

标签: data-structures

简单地说我想检查指定的单词是否存在。

查找需要非常快,这就是我决定将字典存储在trie中的原因。到现在为止还挺好!我的特里没有问题。问题是用字典填充trie。我目前正在做的是循环遍历纯文本文件的每一行,即字典并将每个单词添加到我的trie中。

这是一个非常缓慢的过程,这是可以理解的。该文件只包含大约120 000行。如果有人能指出我能做到的正确方向,我将不胜感激!

这就是我在trie中添加单词的方式(在Boo中):

trie = Trie()

saol = Resources.Load("saol") as TextAsset
text = saol.text.Split(char('\n'))

for new_word in text:
    trie.Add(new_word)

这是我的特里(在C#中):

using System.Collections.Generic;

public class TrieNode {
    public char letter;
    public bool word;
    public Dictionary<char, TrieNode> child;

    public TrieNode(char letter) {
        this.letter = letter;
        this.word = false;
        this.child = new Dictionary<char, TrieNode>();
    }
}

public class Trie {
    private TrieNode root;

    public Trie() {
        root = new TrieNode(' ');
    }

    public void Add(string word) {
        TrieNode node = root;
        bool found_letter;

        int c = 1;
        foreach (char letter in word) {
            found_letter = false;

            // if current letter is in child list, set current node and break loop
            foreach (var child in node.child) {
                if (letter == child.Key) {
                    node = child.Value;
                    found_letter = true;
                    break;
                }
            }

            // if current letter is not in child list, add child node and set it as current node
            if (!found_letter) {
                TrieNode new_node = new TrieNode(letter);
                if (c == word.Length) new_node.word = true;
                node.child.Add(letter, new_node);
                node = node.child[letter];
            }

            c ++;
        }
    }

    public bool Find(string word) {
        TrieNode node = root;
        bool found_letter;

        int c = 1;
        foreach (char letter in word) {
            found_letter = false;

            // check if current letter is in child list
            foreach (var child in node.child) {
                if (letter == child.Key) {
                    node = child.Value;
                    found_letter = true;
                    break;
                }
            }

            if (found_letter && node.word && c == word.Length) return true;
            else if (!found_letter) return false;

            c ++;
        }

        return false;
    }
}

2 个答案:

答案 0 :(得分:3)

假设您没有任何严重的实施问题,请为填充trie付出代价。在您填充trie后,将其序列化为文件。为了满足将来的需求,只需加载序列化版本即可。那应该更快地重建特里。

- 已添加 -

仔细查看您的TrieNode课程,您可能希望将用于Dictionary的{​​{1}}替换为数组。您可能会占用更多空间,但查找时间会更快。

答案 1 :(得分:0)

您自己使用CLI做的任何事情都会比使用内置函数慢。 120k并不是一本字典。

我要做的第一件事是启动代码性能工具。

但只是一些猜测:你有很多函数调用。刚开始使用for循环中的Boo C#绑定。尝试传递整个文本块并用C#将它分开。

其次,不要使用词典。现在,您只需使用代码就可以浪费尽可能多的资源。

第三,在插入之前对文本进行排序 - 你可以用这种方式进行一些优化。也许只是构建一个后缀表。