在文字聊天室场景经常会碰到一些敏感词的问题,那么如何快速高效实时的将聊天语句中的敏感词检索出来呢?敏感词的检索也是子串匹配,所以首先我们想到的是Boyer-Moore算法,但是Boyer-Moore算法似乎更适合文本子串查找,因为如果使用Boyer-Moore算法的话时间复杂度会随着敏感词的增加而增加的,那么可以比较合适的解决方案?答案是前缀树算法
算法原理
前缀树的构建
中文的前缀树和英文的前缀树有一个比较大的差别,英文的前缀树的节点使用数组加尾节点标志的方式,显然中文不可能是用数组的模式,比较相比英文的26个字母元素咱们的中文汉字可是有10w+的,中文前缀树的节点是尾节点标志加hash map的模式,使用hash map不仅可以节约海量的内存(虽然前缀树算法是内存换时间,但是也不能浪费不是吗),还能保证绝对的速度(hash map查找时间复杂度是O(1)),构建树如下:
节点的map的存储了以敏感词前缀为key的节点指针,敏感词的末尾以标志位标记。
敏感词匹配
假设有句话是这样的:
首先让begin(敏感词的起点)和position(游标)指向语句起始位置,tempNode(树的游标),然后遍历语句,取出第一个字“太”,到tempNode指向的节点的map中查找"太"的元素,发现没有,begin和position都向后移动tempNode恢复指向树的root节点,当去到达‘日’的时候,我们在tempNode指向的节点查找到了元素,position后移,bigin不动,tempNode指向’本’,此时节点有末尾标志,记录此时的begin 和position,postion继续下移,此时’是’未找到,tempNode指向root,如此反复操作
代码实现
TreeTrie.h
#pragma once
#include <unordered_map>
#include <string>
class TreeNode {
public:
bool isEnd = false;
std::unordered_map<wchar_t, TreeNode*> subNodes;
};
class TreeTrie {
private: