在n条短信中查找m个关键字,怎么让时间复杂度不是n*m
现在有一个海量的用户短信文件(n量级),每一行是用户的一个短信。此时,还有一个海量的关键词库(m量级),每一行是一个关键词。给出一种数据结构的设计,统计在用户的短信中,出现频率最高的前10个关键词。
我的解法:
首先,该问题并非短信的判重或者计频,因此无法用HASH表或者Trie树来解决。关键词在字符串内的查找属于模式匹配问题,推荐是用KMP算法。
其次,由于用户短信数据是海量的,因此无法一次性加载到内存中,必须对用户文件进行切割,切割过程考虑使用HASH映射的方式进行。我们将SHA 1 HASH值对1024取模相同的短信数据放置到同一个文件碎片当中。 文件切割耗时是O(n),其中n是短信数据的量级。
其三,关键词库也非常大,无法一次加载到内存中,于是还需要对关键词库进行分割。关键词库同样按照SHA1 HASH 取模的方式分割为各个碎片,切割耗时是O(m)。m是关键词库的规模。当然,如果关键词出现同样前缀的情况较多的话,用Trie来分割关键词也不错。比如CCNA和CCTV就有CC这两个共同的前缀。
取短信文件的每一部分,对所有关键词文件的每一分片查找各个短信中出现的关键词,并统计频率。我能想到的算法还只能停留在对每一个短信检索所有关键词的地步,这个真是求超越。整个模式匹配的时间是O(n*m)。
生成一个10个元素大小的小顶堆,对每一个关键词分片文件中统计的频率进行堆排序,其算法是如果频率大于堆顶,则堆顶元素就被该关键词的频率代替并重新调整堆。这样就求出了每一个关键词文件分片的TOP10. 然后再把这些统计结果归并再求TOP10. 对于空间来说是O(1),对于时间来说是O(M*10log10)。