记一个n*m算法复杂度的优化过程

来源:互联网 发布:arm是单片机吗 编辑:程序博客网 时间:2024/06/12 20:00

需求:

一份关键字文件按行存储,数量大概在3-4万。
一份待查文件按行存储,大概在150万行左右。


要求遍历关键字文件,找到待查文件中包含该关键字的所有行,然后做聚合计算(本文不讨论聚合计算的问题)。
由于遍历查找的过程是”包含“,因此按照传统方法实现的算法复杂度是n*m.这个实现方法明显是不可接受的。
必须要想出优化方案。


优化方案:

方案一:

由于本人之前对mysql研究比较多,于是想到了myisam引擎的全文索引。


具体实现方案是:
1、将待查文件load data到myisam引擎的表里面。
2、对相应的列创建全文索引。
3、遍历关键字文件,调用mysql查询接口查询全文索引表。


方案分析:
经过实践这个方案主要时间消耗在创建索引上,因为mysql的全文索引是比较耗时的,查询耗时也不少,平均在1.5秒左右。
不过比起最原始的方案,已经有了比较明显的优化,但还是不能满足最终性能的要求。


方案二:

想到了之前研究lucene的时候倒排序索引的原理,是可以借鉴过来的。


具体实现方案是:
1、对待查文件每行进行分词。
2、将切好的词与待查文件的每行建立映射关系,key:关键字,value:待查文件的行的list.
3、查询时之间map.get(key)就行。


主要讲讲分词。
对于分词当然就需要词库,这里很简单,关键字文件就是词库。也就是说拿关键字作为词库对待查文件的每行进行分词,然后建立二者之间的mapping关系。
其实这就是一个倒排序的过程,算法复杂度由n*m降低到了n的复杂度。


对于分词工具得选择,我采用了mmseg4j,但mmseg4j有个弊端,如果词库中有中文+ask码字符的词时,它是不能按要求切分的。
于是看了下mmseg4j的源码,简单的修改了下源码,实现了我的要求。




第一次写博客,如果有不准确的地方请大家多多指导。
0 0
原创粉丝点击