敏感词过滤实践
敏感词过滤Java实现
基本思路
针对于敏感词集合,构建成前缀树,树的末尾记录整个词
对于Java来说可以使用HashMap来模拟数的节点,便于查找
待检测句子进行遍历,在树中寻找,如果存在,就沿着树寻找,直到发现结束标志,一旦发现结点不存在,直接跳出树,去下一个字符。
实现
前缀树的构建
/**
* 创建树
*/
private static Map<Character, Object> buildTree(List<String> list) {
// 返回的树根
HashMap<Character, Object> baseMap = new HashMap<>();
// 开始遍历
for (String s : list) {
HashMap<Character, Object> currMap = baseMap;
char[] chs = s.toCharArray();
for (int i = 0; i < chs.length; i++) {
// 当前层级不存在该字符
currMap.computeIfAbsent(chs[i], k -> new HashMap<Character, Object>());
// 进入下一层
currMap = (HashMap<Character, Object>) currMap.get(chs[i]);
// 最后一个字符
if (i == chs.length-1){
// 最后一个节点直接存储整个字符,便于过滤时进行的统计
currMap.put('$',chs);
}
}
}
return baseMap;
}
敏感词检测
/**
* 检测句子
*/
public static List<String> scan(String text,Map<Character, Object>wordTree){
char[] chs = text.toCharArray();
Map<Character, Object> currMap = wordTree;
List<String> triggerWords = new ArrayList<>();
for (char ch : chs) {
// 当前字符无敏感词
if (currMap.get(ch) == null){
currMap = wordTree;
continue;
}
currMap = (HashMap<Character, Object>) currMap.get(ch);
// 到达了敏感词结尾 表明触发了敏感词
if (currMap.get('$') != null) {
triggerWords.add(new String((char[])currMap.get('$')));
currMap = wordTree;
}
}
return triggerWords;
}
测试案例
public static void initTree(){
List<String> list = Arrays.asList("傻子", "傻逼", "圣诞", "你好");
Map<Character,Object> preFixTree = buildTree(list);
System.out.println(preFixTree);
System.out.println("触发敏感词"+scan("我是大傻逼,你好圣诞呀", preFixTree));
}
返回
{你={好={$=[C@4534b60d}}, 圣={诞={$=[C@3fa77460}}, 傻={子={$=[C@619a5dff}, 逼={$=[C@1ed6993a}}}
触发敏感词[傻逼, 你好, 圣诞]