中文分词
这个分词算法是基于网上一个叫IK分词算法(这里并没有使用我的那个敏感词过滤算法)!我只是将它的词表进行了优化和补充。在这个IK算法基础上主要做的就是将Lucene部分去除,只留下核心的分词逻辑。
相关词搜索
这个部分是使用敏感词查找算法的理念,但算法上不同!所谓相关词搜索,就是从指定的词中查找出词库中所有与这些词相关的词,也就是从一个词的集合中查找另一个词的集合!这个逻辑与场景不同于从一个目标文本中匹配指定词库中的词,它相当于从若干个目标文本中匹配指定词库中的词!
这里的算法思想是:先将所有词库中的词存储在一张定义的内存表中,每个词进行编号,然后将词库中的所有词中的每个字建立索引,索引信息中说明该字在哪些词中拥有(即记录这些词的编号信息),在匹配时,将目标词进行循环处理,处理方式为:看目标词的第一个字有没有在索引中,如果有,取出这个索引中的所有词,然后再用indexOf进行判断是否存在,否则直接通过!在查找出所有相关词的同时会按照得分进行排序(相关词的数据结构为compareable)并最终返回查找到的相关词。
这里需要解释的是,因为目标词库中的词基本上不会太多,因此这个算法在效率上还是没有多大问题的!
高亮显示
这个算法使用的是敏感词查找算法!这里对查找的过程不再说明,现在说明一些替换的方式:在替换逻辑上,考虑到不同场景使用不同的高亮方式,因此这里的接口输入的是一个Formatter抽象类,用户可以根据自己不同的需求自己扩展高亮方式!系统中默认实现了一个HTML方式的高亮实现类。
其中Formatter类的代码为:
public abstract class Formtter { /** * 将指定的字符串用该格式化器进行格式化操作! * * @param text 预处理的内容 * @return 返回处理过的内容 */ public abstract String format(Lexeme word); /** * 获取格式化的开始标志符号 * * @return */ public abstract String getStartTag(); /** * 获取格式化的结束标志符号 * * @return */ public abstract String getEndTag(); }
目前还存在一些问题:不能很好有效地解决带有特殊内容的高亮,如带有格式的信息,如XML、HTML等!
汉字与拼音互转
在搜索规划路线上,我们要求后期实现根据用户输入的词还要提示用户可以查找与之拼音相同的词,这样可以做到帮用户进行一定的纠错和提示,如用户输入“港铁”,则系统会提示用户可以输入“钢铁”查询试试。
这个功能的算法理念也是基于敏感词过滤算法。但所不同的地方在于汉字与拼音的转换过程中对多音字的处理一定要准确!因此这里的重点是如何处理多音字的拼音与汉字的转换问题。
在汉字转换为拼音时,要分清楚哪个多音字该发什么音,这时可以将所有多音字的词语作为词库,将整个目标文本中的多音字词语转换为拼音,剩下的字就可以直接转换为拼音了,如果有的多音字词语没有被完整收录,则显示它的所有拼音的情况!
在拼音转换为汉字时,因为每个拼音都有若干个字,因此需要尽量将词语对应的拼音作为词库,将整个目标文本中的词拼音转换为对应的词语,然后其余的进行汉字转换,如果一个发音有多个汉字,则显示它的所有汉字的情况。
在整个转换过程中,如果遇到不需要转换的内容,则直接保留下来!另外,这个算法还有需要完善的地方:如增加词的排序功能(因为根据业务不同,词的得分情况也不同,所以应该在转换时,将得分靠前的词优先匹配并将整个结果靠前)、有时候不能做出精确的拼音到汉字的转换,如“change”可能会被转换为“谗歌”等(当然这仅仅只是一个例子,真正情况下只可能转换为“嫦娥”,因为词典中有这个词与拼音)。
相似度匹配
其算法原理基于三个个:敏感词过滤算法、分词算法与最小编辑距离算法。
敏感词过滤算法是将词当中的一些无意义的词过滤掉,如:“有限公司”等。
分词算法的作用是将过滤剩下的内容进行分词,并将这些词建立索引,便于缩小计算的集合范围。
最小编辑距离的作用是计算两个字符串之间的相似度。因此,其算法的完整过程可以描述如下(如果以后这块数据太大,而且需求变大,则将采用搜索服务来处理):
- 将所有集合信息(如所有已审核的公司名称)去除无意义词(如地名、“有限公司”等词)之后,分词建立索引;
- 将用户输入的词进行去除无意义的词之后,分词,并用这些分词从集合中查询出所有相关的信息;
- 对这些查询出来的信息进行相似度计算,将相似度超过阀值的保存并按照相似度降序排列(即相似度越高排越前面)