我有一个大约10^5
英文单词及其初始频率的列表。我想写一个单词完成建议程序,它将返回一个最大k
个单词列表,从给定的前缀开始,按其频率的降序排序。数据结构还应该能够将单词的频率计数更新为1(无论何时使用单词)。
例如 -
鉴于' engin'作为前缀和k = 3
,它应该返回如下列表 -
{{17,"引擎"},{10,"工程师"},{4,"工程"}}
k
的值应在[1,15]之内。
Trie
数据结构应该足够了,但确实如此。任何人都可以提醒我任何数据结构或解决这个问题的方法吗?
注意:Trie
数据结构占用太多空间。对于这种数据结构,我似乎无法承担10MB
。另外,如果我使用与trie节点相关联的最大堆(至少高达3/4深度),则内存消耗将变为巨大。
现在我试过这个 -
保持4个有序集(指针,指向字符串)。
集i
是指向string length >= i
已排序 -
i
个字母的字典顺序这很好用,考虑到我需要O(4n log2(n))时间和O(n log2(n))空间进行初始化。对于每个查询,我的查找时间复杂度为O(log2(n)),在最坏的情况下加上最多约100个字的遍历。要更新单词的频率,需要O(8 * log2(n))时间。
答案 0 :(得分:1)
这可以通过两种数据结构的组合来完成:trie和segment tree。 (如果字典是静态的,k
不是很大)。
在为字典构造trie之后,使用属于该节点的第一个/最后一个字的索引来扩充每个trie节点。例如,节点' engin'可以为"引擎"存储索引1001 " engineering"。索引1003。
搜索k
字词列表时,首先在trie中搜索给定的前缀。然后使用第一个/最后一个单词索引来执行k
范围最大查询。每次查询后,将找到的字词的频率计数暂时设置为-1
。
使用段树数据结构进行范围最大查询。 (有关详细信息,请参阅tutorial at TopCoder。)
此方法允许及时处理每个查询O(prefix_size + k * log(dict_size))。计数器更新需要O(log(dict_size))时间。初始频率以O(dict_size)时间加载。
其他替代方法是在trie的每个节点中存储k_max
{counter,index}对的排序数组。
应在O(k_max * dict_size)时间内以自下而上的顺序(使用DFS)在每个节点处合并更新初始频率。每个计数器更新需要O(k_max * word_length)时间。前缀k查询在O(prefix_size)时间内提供。下行的内存要求要高得多。
答案 1 :(得分:0)
为什么不是特里?您可以为计数器使用额外的数据字段,并为搜索算法添加排序算法。更新计数器和trie也很快。如果你只想要k个最大/最高边缘,那么它会更快,因为你不需要对所有这些进行排序。