Algorithm Aho FSA的三元树vs trie和map作为过渡表
使用三元树的FSA和将转换表实现为搜索树(例如std::map)的trie之间有什么区别?看起来两者都有O(logk)复杂度来读取一个符号和O(S)内存复杂度,其中k是字母表大小,S是所有接受的输入字符串的长度之和Algorithm Aho FSA的三元树vs trie和map作为过渡表,algorithm,trie,finite-automata,ternary-search-tree,aho-corasick,Algorithm,Trie,Finite Automata,Ternary Search Tree,Aho Corasick,使用三元树的FSA和将转换表实现为搜索树(例如std::map)的trie之间有什么区别?看起来两者都有O(logk)复杂度来读取一个符号和O(S)内存复杂度,其中k是字母表大小,S是所有接受的输入字符串的长度之和 如果我们不需要在运行时更改自动机,那么最好的选择不是使用(符号、状态)转换对的排序向量和二进制搜索吗?三元搜索树(TST)和在每个节点上用二进制搜索树实现的Trie之间没有真正的区别。事实上,您可以将后者视为前者的(低效)实现;TST的优点是易于优化,并且空间开销合理 经典的Trie
如果我们不需要在运行时更改自动机,那么最好的选择不是使用(符号、状态)转换对的排序向量和二进制搜索吗?三元搜索树(TST)和在每个节点上用二进制搜索树实现的Trie之间没有真正的区别。事实上,您可以将后者视为前者的(低效)实现;TST的优点是易于优化,并且空间开销合理 经典的Trie在决策节点上使用直接查找,并使用符号索引的转换向量。这是
O(1)
时间,但空间需求很大。尽管如此,还是有一些方法可以优化存储。此外,还存在混合解决方案,其中Trie结构仅用于树顶部的宽决策节点;一旦候选数量减少到一定数量,就可以使用快速扫描或哈希表来查找合适的候选
以简单的方式使用(符号、状态)转换的排序向量需要每个转换的O(logt)
时间,其中T
是转换的总数;本质上是所有输入字符串的总大小。给定目标的总时间为| target |*log(T)
相比之下,TST每次转换所需的时间不超过
O(logs)
时间,其中S
是字母表的大小;这个数字比T
小得多。此外,整个目标字符串上的查找总数受输入字符串数量的限制,因此整个查找的总和要小于|target |*log
,考虑到Aho Corasick的说明
这是我的节点:
public class AhoCorasickNode
{
// This part works as a Trie
public char literal; // c
public String stack; // abc
public AhoCorasickNode previous; // { ab }
public AhoCorasickNode[] next; // { abca }, { abcb }, { abcc }, ..
//-----------------------------
// This part is used when solving
boolean inDictionary;
public AhoCorasickNode suffix;
public AhoCorasickNode dictionarySuffix;
}
资料来源: