1. 问题原型:
给定一段UGC文本或者网页文本,其中含有很多的敏感词或者无效词,但是有一些词只有和其他词一起出现的时候才算是敏感词,我们称其为组合敏感词,需要一种算法,找到其中的组合敏感词和单个敏感词
2. 求解思路:
2.1 单敏感词求解:
2.1.1 暴力求解:
将文本内容逐个和设定的敏感词(以下称之为模式)进行比较,算法的复杂度为O(m*n*k),其中m为文本长度,n为模式的数量,k为模式的总长度,显然,这种复杂度的算法是不可取的,那么接下来我们看有哪些改进算法
2.1.2 一个模式的匹配:
对于一个模式的比较,有很多算法,比较经典的有KMP和Boyer-Moore。
他们改进的思路是,对于单个的模式而言,已经比较过的文本就不需要再回去比较了,也就是去掉了所谓的回溯过程。有些多模式匹配算法也借鉴了这种思想,可以说,有些多模式匹配算法就是泛化的单模式匹配,网上关于以上两种算法的介绍有很多,这里不再赘述。
单模式匹配对于我们2.1的问题的时间复杂度为O(m*n+k),可以想象,如果模式的个数达到10W级别,这种复杂度也是难以忍受的
2.1.3 多模式匹配:
1. 字典树(比如trie树或者其他的改进算法double-trie),建立一颗字典树来存放所有的模式,其时间复杂度为O(m*k),可以看到其时间复杂度还不是非常让人满意
2. 自动机(比如AC自动机等),通过自动机的状态之间的转移来避免回溯问题,其时间复杂度为O(m+z),其中z为模式在文本中出现的长度之和,再看这个算法的时间复杂度:随着文本的长度线性增长,木有一个乘号,完美。(自动机的建立和查找过程可以参考网上资料)
现在,我们已经可以很好的解决了单个敏感词的问题,那么,对于组合型敏感词我们应该怎么处理呢?
2.2 组合关键词处理
比如:给定组合敏感词词组:A,B。词A和词B在单独出现的时候不是敏感词,但当A和B一起出现的时候,A和B是组合敏感词。求解步骤:首先我们可以把A、B和其他的单个敏感词都当成是关键词(区别于敏感词)放到上面提到的自动机中,当一段同时包含A、B和一些其他关键词的文本输入时,通过自动机的状态转移会分别找出词A、词B和其他关键词(比如D),那么重点来了,我们怎么确定其中包含哪些单个敏感词和组合敏感词呢?
2.2.1 暴力求解:
1). 遍历给定的单敏感词,如果自动机中找到的关键词(比如A、B、D)和给定的某个单敏感词(比如D)相等,则这个关键词D为单敏感词,这样的话,时间复杂度为O(x*a*b),其中x为找到的关键词总长度,a为单个敏感词数量,b为单个敏感词总长度,**!
(
其实如果大家对以上的过程充分理解的话,对于这个过程可以这样优化(说好的要暴力求解呢
):再建一个只包含单个敏感词的自动机来查找,至于为什么,大家可以独立思考一下,这样的话时间复杂度可以忽略不计)
2). 遍历给定的组合关键词词组,如果自动机中找到的关键词(比如A、B、D)完全包含某个给定的关键词词组(A,B)的话,说明关键词A和关键词B为组合敏感词A,B。
时间复杂度O(x*y)其中x为文本中的关键词数量,y为组合敏感词的数量。oh my god,怎么又出现了乘号。
2.2.2 基于倒排索引的组合敏感词查找
1). 基于倒排索引的组合敏感词查找,首先,对于组合敏感词中出现的每个单个关键词,建立倒排索引。举个栗子:(1)组合敏感词A,B 中含有关键词A和关键词B,(2)组合敏感词A,C 中含有关键词A和关键词C,(3)单个敏感词D中含有关键词D,那么就建立倒排索引:
A: A,B A,C
B: A,B
C: A,C
D: D
在上面的倒排索引中,关键词A、B、C、D为term,敏感词A,B、A,C、D 为doc(term的存储结构为红黑树,方便查找,倒排索引的存储结构为数组)
2). 回到2.2描述的问题,如果通过自动机的状态转移找到了关键词A、B、D,那么怎么判断其中包含哪些组合敏感词和单个敏感词呢?
首先,分别找到A、B、D所对应的倒排索引,分别是(1)A: A,B A,C (2) B: A,B (3)D: D
此时,候选的敏感词有 A,B A,C 和 D,不过很明显, 组合关键词 A,C 是不应该出现在结果中的,因为只有A,没有C, A,C 只是部分出现。那么怎么判断到底哪些是完全出现哪些是部分出现呢?
有一个tip可以解决这个问题:计算每组敏感词在倒排索引中总共出现的次数count,然后和该敏感词所含有的关键词的数量num做比较,如果相等,则该敏感词为最终结果。
什么意思,简单解释一下:敏感词A,B 在上面的倒排索引(1)和(2)中总共出现了两次,而该敏感词含有两个关键词A,B,所以,A,B 是完全出现,同理,敏感词A,C在倒排索引中只出现了一次,却有两个关键词,所以A,C 是部分出现;敏感词D出现一次,只有一个关键词,所以D也是完全出现
这样,应用自动机和搜索引擎原理再加上一个小tip就解决了单个敏感词和组合敏感词的过滤问题
最后让我们来看一看基于倒排索引的组合敏感词过滤时间复杂度是多少:O(x*logy),x为文本中的关键词数量,y为关键词的总数量(由于红黑树存储的结构使查找复杂度变为logy),虽然还有乘号,但有log啊,即使是设定的敏感词数量达到1M级别,这种算法的耗时依旧是很低的,完美
说了这么多,其实就是一句话:用搜索引擎的思想来解决组合敏感词过滤的问题
-----------------分割线-------------------
感觉最近输入好多,输出很少,接下来应该会准备一篇关于最近在数据挖掘上的小感悟