------ 本文是学习算法的笔记,《数据结构与算法之美》,极客时间的课程 ------
很多支持用户发表文本内容的网站,比如BBS,大都会有敏感词过滤功能,用来过滤掉用户输入的一些反动谩骂等内容。你有没有想过,这个功能是怎么实现的呢?
实际上,这些功能最基本的原理就是字符串匹配算法,也就是通过维护一个敏感词的字典,当用户输入一段文字内容之后,通过字符串匹配算法,来查找用户输入的这段文字,是否包含敏感词。如果有,就用字符给替代掉。
我们前面讲过好几种字符串匹配算法了,它们都可以处理这个问题。但是,对于访问量巨大的网站来说,比如淘宝,每天的评论数有几亿,甚至几十亿。这时,对敏感词过渡系统的性能要求就很高。毕竟,我们也不想,用户输入内容之后,要等几秒才能发送出去吧?我们也不想,为了这个功能耗费过多的机器吧?那如何才能实现一个高性能的敏感词过渡系统呢?这就要用到今天的多模式匹配算法。
基于单模式串和Trie树实现的敏感词过滤
我们前面讲了多种字符串匹配算法,有BF算法、RK算法、BM算法、KMP算法,还有 Trie 树。前面四种都是单模式匹配算法,只有 Trie 树是多模式匹配算法。
我说过,单模式串匹配算法,是在一个模式串和一个主串之间进行匹配,也就是说,在一个主串中查找一个模式串。多模式串匹配算法,就是在多个模式串和一个主串之间做匹配,也就是说,在一个主串中查找多个模式串。
尽管,单模式串匹配算法也能完成多模式串的匹配工作。例如开篇的思考题,我们可以针对每个敏感词,通过单模式串匹配算法(比如KMP算法)与用户输入的文字内容进行匹配。但是,这样做的话,每个匹配过程都需要扫描一遍用户输入的内容。整个过程下来要扫描多次用户输入的内容。如果敏感词很多,比如几千个,并且用户输入的内容很长,假如有上千个字符,那我们就需要扫描几千遍这样的内容。很显然,这种处理思路比较低效。
与单模式匹配算法相比,多模式匹配算法在这个问题上处理就很高效了。它只需要扫描一遍主串,就能在主串中一次性查找多个模式串是否存在,从而大大提高匹配效率。我们知道,Trie 树是一种多模式串匹配算法。那如何用 Trie 实现敏感词过滤功能呢?
我们可以对敏感词字典进行预处理,构建成 Trie 树结构。这个预处理的操作只需要做一次,如果敏感词字典动态更新了,比如删除、添加了一个敏感词,那我们只需要动态更新一下 Trie 就可以了。
当用户输入一个文本内容后,我们把用户输入的内容作为主串,从第一个字符(假设是字符C)开始,在 Trie 树中匹配。当匹配到 Trie 的叶子节点,或者途中遇到不匹配字符的时候,我们将主串的开始位置后移一位,也就是从字符C的下一个字符开始,重新在 Trie 树中匹配。
基于 Trie 树的这种处理方法,有点类似单模式串匹配的BF算法。我们知道,单模式串匹配算法,KMP算法对BF算法进行改进,引入next数组,让匹配失败时,尽可能将模式串往后多滑动几位。借鉴单模式串的优化改进方法,能否对多模式串 Trie 树进行改进,进一步提高 Trie 的效率呢?这就要用到AC自动机算法了。

本文探讨了AC自动机算法在多模式匹配中的应用,特别是在敏感词过滤系统中的高效性能。通过对敏感词构建AC自动机,包括Trie树及失败指针,实现了在主串中快速查找多个模式串。
2356

被折叠的 条评论
为什么被折叠?



