列出以固定前缀开头的`k`字,其频率按降序排列

时间:2014-09-29 09:40:42

标签: algorithm sorting data-structures trie n-gram

我有一个大约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))时间。

2 个答案:

答案 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个最大/最高边缘,那么它会更快,因为你不需要对所有这些进行排序。

相关问题