Trie树的各种实现

原创
2018/03/05 15:04
阅读数 2.3K

前缀匹配在自然语言处理中常见的需求。 假设有一个词典和一个句子,找出句子开始位置处匹配的词典中的单词。

Hash标记法

使用一个HashMap,放入词典中词的同时放入前缀词。例如当插入词典中的hello这个词时,同时插入hello的前缀词。

map["hello"] = 1
map["hell"] = 0
map["hel"] = 0
map["he"] = 0
map["h"] = 0

这样查找遇到0的时候继续追加字符进行查找。

传统的Trie树

使用utf8编码,每一字节有256中可能的后缀。

TrieNode {
	char ch;
	TrieNode children[256];
}

这种方式在汉字处理有很多空间浪费。

字节分割法

传统的Tire树只能存储英文。如果是汉字,可以按字节来分割。例如utf8编码有3个字节,我们没半个字节分一个数出来,那么一个汉字专为6个字母。

Hash基础的Trie

孩子结点放入一个哈希表中。

TrieNode {
	char ch;
	Map<char,TrieNode*> children;
}

缺点是序列化不太方便,占用内存大。

二分数组基础的Trie

孩子结点排序,然后进行二分查找。

TrieNode {
	char ch;
	Array<TrieNode> children;
}

二分查找可能没有其他方式快。插入时也要移动内存。

Double Array Trie

整个trie被存储为base和check两个数组。相当于将子结点数组压缩到一个单个数组中。

详见

DoubleArrayTrie容易序列化,但构建速度较慢。

Radix Trie

大概意思是将只有一个子结点和父节点合并,来压缩trie树。

Aho-Corasick

这是一个自动状态机算法,用在多模式匹配。类似与KMP算法的思路,在匹配失败的情况下转移到远的结点。t

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部