您的位置:首页 > 其它

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

2015-01-08 17:34 169 查看

需求:

一份关键字文件按行存储,数量大概在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的源码,简单的修改了下源码,实现了我的要求。

第一次写博客,如果有不准确的地方请大家多多指导。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: