【发布时间】:2013-09-28 14:48:21
【问题描述】:
我正在制作一个需要数千次快速字符串查找和前缀检查的移动应用程序。为了加快速度,我从我的单词列表中做了一个 Trie,它有大约 180,000 个单词。
一切都很好,但唯一的问题是在我的手机上构建这个巨大的树(它有大约 400,000 个节点)大约需要 10 秒,这真的很慢。
这是构建 trie 的代码。
public SimpleTrie makeTrie(String file) throws Exception {
String line;
SimpleTrie trie = new SimpleTrie();
BufferedReader br = new BufferedReader(new FileReader(file));
while( (line = br.readLine()) != null) {
trie.insert(line);
}
br.close();
return trie;
}
在O(length of key) 上运行的insert 方法
public void insert(String key) {
TrieNode crawler = root;
for(int level=0 ; level < key.length() ; level++) {
int index = key.charAt(level) - 'A';
if(crawler.children[index] == null) {
crawler.children[index] = getNode();
}
crawler = crawler.children[index];
}
crawler.valid = true;
}
我正在寻找直观的方法来更快地构建 trie。也许我只在笔记本电脑上构建了一次 trie,以某种方式将其存储到磁盘上,然后从手机中的文件中加载它?但我不知道如何实现。
或者是否有其他前缀数据结构可以花费更少的时间来构建,但具有类似的查找时间复杂度?
感谢任何建议。提前致谢。
编辑
有人建议使用 Java 序列化。我试过了,但这段代码非常很慢:
public void serializeTrie(SimpleTrie trie, String file) {
try {
ObjectOutput out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
out.writeObject(trie);
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public SimpleTrie deserializeTrie(String file) {
try {
ObjectInput in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)));
SimpleTrie trie = (SimpleTrie)in.readObject();
in.close();
return trie;
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
上面的代码可以更快吗?
我的特里:http://pastebin.com/QkFisi09
词表:http://www.isc.ro/lists/twl06.zip
用于运行代码的Android IDE:http://play.google.com/store/apps/details?id=com.jimmychen.app.sand
【问题讨论】:
-
我无法在安卓姜饼上安装 ide?span>
-
我建议从分析开始。至少测量哪个部分用于(1)从文件读取,(2)在 trie 中查找位置和(3)创建新节点
-
@Bruce 你试过二分搜索技术吗?我看到了很好的结果。
-
@Justin 是的,我确实尝试过,但似乎并不太快。我只需要两个查询:是否存在前缀,是否存在单词。我不需要所有以前缀开头的字符串。顺便说一句,我计算了前缀存在搜索的数量,大约是 10,000.. 所以二进制搜索方法比较慢,因为使用 dawg,whole 算法在大约 60 毫秒内完成。
-
@Bruce 好的,很高兴您找到了解决方案。我从来没有找到比 1 毫秒慢的前缀查询,并且与单个字符串的存在相同,但也许我有一个更快的电话。
标签: performance algorithm optimization data-structures trie