我正在尝试找出实现类似效率的最有效方法,就像使用Trie存储英语单词一样,但我希望将单词存储在没有字母的语言中,例如中文。例如,我希望能够加载单词列表并拥有一个应用程序,当用户键入时,该应用程序会根据已输入的字符实时提供建议。任何建议如何实现这一点就像我使用Tries一样,我将拥有大量的父节点,因为有数千个独特的字符。有没有确定的方法来实现我上面描述的内容?
答案 0 :(得分:5)
术语绕道:“字母”一词通常用于指代书写系统中的符号(如各种欧洲语言中的符号),其中每个符号大致对应于单个音素(声音)。还有写作系统,其中符号对应于音节,语素或整个单词;这些语言的符号比字母表要多得多,它们有不同的技术名称:syllabaries,abugida,logographs等,但歧视并不准确。
然而,在计算理论中,通常使用“字母”一词来描述任何有限的符号集合,无论该集合的大小有多大。任何字母表 - 或有限的符号集 - 都可以从大小至少为2的较小字母表转码为固定长度的序列,长度的变化是字母表大小的对数。因此,通常很容易假设只使用二进制表示:即字母{0, 1}
中的表示。
trie适用于任何字母大小;没有要求特里的字母表是来自人类书写系统的“字母表”,也没有禁止它作为更大的符号集合,尽管使用大字母表的天真实现可能非常浪费空间。特别是,没有什么可以阻止你使用原始书写字符重新编码为较小的字母表,每个字符使用几个trie级别。例如,如果原始字符串以UTF-8表示,那么您可以使用单个字节(并且您可能希望区分前导节点,其中字母大小为178,尽管只有99对应于“字母”)和内部节点,字母大小为64)。或者,您可以将Unicode代码点拆分为三个或四个位序列,每个位序列都是可管理的大小。
您可以通过压缩只有一个子节点的连续节点来优化尝试;这可能对上述方案有效。二进制字母表上的一个紧凑的trie被称为Patricia trie,它也值得一看。
处理稀疏特里节点的另一个常见解决方案是为子节点使用某种关联结构,而不是数组。在ternary search trees中,子项被简单地保存在一个排序列表中,以便在字母大小的对数时间内以二进制搜索找到正确的子项,这对于给定的字母表是恒定的。 (时间实际上是儿童数量的对数,可能比字母大小小得多。)
另一种适用于中等大小字母的解决方案是保留现有儿童的一点矢量以及儿童的分类矢量;现代CPU具有可以快速求和字中设置位数的指令,从而可以有效地使用位向量来查找向量中子项的索引。
另一种可能的解决方案是使用一个哈希表,其条目由一个由父节点的id和子的前导字符组成的2元组进行键控。这种数据结构易于维护且节省空间,但具有非常差的参考局部性。 (一个缺点是需要完成额外的工作来构建父节点的子节点列表:例如,通过显式链接子节点。)