背景

平时我们在逛贴吧的时候,我们经常可以看到一些形如 “***”的符号,通过上下文,我们也可以很容易猜到这些词原来是骂人的话,只是被系统和谐了。那么这是如何实现的呢?作为普通人,我们最先想到的一种办法就是把所有敏感串存入一个列表中,然后用户每发一条内容后台就把该内容与敏感串列表的每一项进行匹配,然后把匹配的字符进行和谐。显然这样的效率是很低的。非常影响性能,那么我们有没有其他的算法呢?这就是我这篇博文打算介绍的。

原理讲解

1.首先建立个敏感词前缀树

根节点为空

2.准备好待处理字符串: 哈哈大王八子大猪蹄子哦 ,声明三个指针,分别指向前缀树的根节点以及待处理字符串的开始字符

3.position指向的字符与根节点的所有子节点进行匹配,不匹配,position 和 begin分别指向待处理字符串的下一个字符,tempNode依旧指向 根节点

4.依旧不匹配,position 和begin继续向前走一位,指向“大”,treeNode依旧指向根节点

5.此时 根节点有一个子节点 与 position指向的字符相等,都为‘大’,则tempNode 指向该节点,同时position前进一步,指向‘王’

6.此时把position指向的‘王’ 和 tempNode的所有子节点进行匹配,匹配失败,说明 从begin起头所有串是不存在敏感词的,可以直接输出。此时begin前进一位,position回退到begin的位置,tempNode回退到根节点

7.此时再把position指向的‘王’与tempNode的所有子节点进行匹配,匹配成功,所以tempNode指向该节点,同时position前进一位,指向'八'

8.此时再把position指向的‘王’ 与tempNode的所有子节点进行匹配,匹配成功,此时tempNode 指向它的子节点‘八’,同时position前进一位。

9.继续把position指向的字符与tempNode的所有子节点进行匹配,匹配失败。说明以begin起头的不存在非法字符,可以加入到结果集中。 此时begin向前走一位,position回退到begin的位置,同时tempNode回退到根节点。

10.同理,可以发现子'子'不匹配,则直接把它加入结果集,同时position 和begin 向前走一位,tempNode指向根节点。

此时position指向 ‘大’,与tempNode的所有 子节点进行匹配,匹配成功,则position和tempNode都走一位,循环执行....

直到position指向‘子’,tempNode指向‘蹄’

11.此时把position与tempNode的所有子节点进行匹配,匹配成功,tempNode指向它的子节点‘子’,此时检查发现tempNode是敏感词树的叶子节点,说明从begin+1开始的位置 到 position这段是敏感词,用和谐词替换掉。替换之后position前进一位,begin跳到position的位置,tempNode回退到根节点

以上,就是全部流程啦,理解了之后看代码就简单多啦

代码讲解

1.前缀树节点结构

private class TreeNode{

//是否最后一个字
private boolean isKeyWordsEnd = false;

//子节点
private Map<Character,TreeNode> subNodes = new HashMap<>();

public void addSubNode(Character key, TreeNode node){
  subNodes.put(key,node);
}

public TreeNode getSubNode(Character key){
  return subNodes.get(key);
}

public boolean isKeyWordsEnd(){
  return isKeyWordsEnd;
}

public void setKeyWordsEnd(Boolean end){
  isKeyWordsEnd = end;
}

2.构建前缀树的方法

public void addSensitiveWord(String words){

  TreeNode tempNode = rootNode;

  for(int i = 0; i < words.length(); i++){

    Character c = words.charAt(i);
    if(!isSymbol(c)){
    continue;
  }

  TreeNode node = tempNode.getSubNode(c);
  if (node == null){
    node = new TreeNode();
    tempNode.addSubNode(c,node);
  }
  // 指针移动
  tempNode = node;

  //如果到了最后一个字符
  if(i == words.length() -1){
    tempNode.setKeyWordsEnd(true);
  }

  }

}
3.算法具体实现

public String filter(String text){

  if (StringUtils.isEmpty(text)){
    return text;
  }

  String sensitiveWords = "***";
  StringBuilder result = new StringBuilder();

  TreeNode tempNode = rootNode;
  int begin = 0;
  int position = 0;

  while (position < text.length()){

    Character c = text.charAt(position);

    //如果非东亚字符,则直接跳过 ??
    if(!isSymbol(c)){ //每次
      if(tempNode == rootNode){
      result.append(c);
      begin++;
    }
    position++;
    continue;
  }

  tempNode = tempNode.getSubNode(c);

  //如果匹配失败
  if(tempNode == null){
  //说明以begin起头的那一段不存在非法词汇
  result.append(text.charAt(begin));
  begin++;
  position = begin;
  tempNode = rootNode;
  continue;
  }else if(tempNode.isKeyWordsEnd()){
    //替换敏感词
    result.append(sensitiveWords);

    position++;
    begin = position;
    tempNode = rootNode;
  }else {
    position++;
  }

}
  result.append(text.substring(begin)); //把剩下的动加入合法集

  return result.toString();
}

小结

最近一直在做项目,所以有一段时间没写文章了,项目也快完成了,就把在项目中使用的一个算法做了下总结,希望能给读者一些帮助。

转载于:https://www.cnblogs.com/hd-zg/p/10591065.html

敏感词过滤算法:前缀树算法相关推荐

  1. 敏感词过滤算法 为内容保驾护航 Java/.Net/C++/c/Python等语言是如何进行敏感词打码限制的 高效防范违规内容

    有人的地方,就有江湖,有输入框的地方,就有注入风险!有输入框的地方,就有敏感词!敏感词就像一个平台杀手,可能直接导致平台被封锁! 敏感词是一个APP.一个网站.一个内容平台的"杀手" ...

  2. trie树之敏感词过滤算法

    之前写过一篇关于Trie树的介绍:Trie树--在一个字符串集合中快速查找某个字符串.今天就用Trie树来实现敏感词过滤算法. 首先简单介绍一下Trie树的数据结构: 1.根节点不存储字符. 2.Tr ...

  3. 【C++】实现敏感词过滤算法(含源码)

    敏感词过滤算法(聚合词树查询法) 1.构建词树 2.敏感词判断 3.遍历文本 关于敏感词过滤算法,数不胜数,在参考众多算法后,选取了比较实用的算法,进行总结与改进.大家可以参考一下链接: 敏感词过滤算 ...

  4. 浅析过滤敏感词过滤算法(C++)

    本文转自浅析敏感词过滤算法(C++),自己也在其基础上根据自己的情况做了一点修改. 为了提高查找效率,这里将敏感词用树形结构存储,每个节点有一个map成员,其映射关系为一个string对应一个Word ...

  5. 通过前缀树的敏感词过滤算法

    敏感词过滤器,配置文件分行写 如: ab cd ef import lombok.Data; import org.apache.commons.lang3.CharUtils; import org ...

  6. 字符串匹配算法 -- AC自动机 基于Trie树的高效的敏感词过滤算法

    文章目录 1. 算法背景 2. AC自动机实现原理 2.1 构建失败指针 2.2 依赖失败指针过滤敏感词 3. 复杂度及完整代码 1. 算法背景 之前介绍过单模式串匹配的高效算法:BM和KMP 以及 ...

  7. 算法-DFA算法-敏感词过滤算法(OC、Swift、Python)

    前言 前段时间,公司的IM SDK想做敏感词过滤,但是后端的小伙伴<比较忙>,在开产品需求会的时候想把敏感词过滤放到前端,让iOS.安卓自己搞,但是前端小伙伴写了一个方法来检测一段文本,耗 ...

  8. 记录一次敏感词过滤算法DFA的应用案例

    目录 0. DFA是什么? 1.为什么要用DFA 2.DFA工具类实现 3.性能对比效果 3.1 普通关键字过滤 3.2 DFA关键字过滤 0. DFA是什么? 参考文档:敏感词过滤的算法原理之DFA ...

  9. java实现敏感词过滤算法DFA并忽略敏感词中的特殊字符

    参考文章:https://blog.csdn.net/chenssy/article/details/26961957 补充说明: 1.具体的DFA介绍参考原文章,此处只是补充了文章中没有介绍的点以及 ...

最新文章

  1. 使用母版页后出现控件,使用FindControl找不到指定控件
  2. php基础知识(2),php基础知识学习(二)
  3. 2021-02-09 带初值的拉氏变换
  4. Graphpad Prism 9绘制子列图与柱状图
  5. (转)DevExpress 汉化(简单、实用、快速)
  6. rxlifecycle 框架的使用
  7. 爬虫笔记:pyquery详解
  8. 《Sibelius 脚本程序设计》连载(五) - 1.2 编辑第一个插件
  9. 带有JWT示例的​​Spring Oauth2
  10. IOC操作Bean管理XML方式(创建对象和set注入属性)
  11. span标签的鼠标滑入提示_彻底搞懂拖拽——基于鼠标事件的拖拽以及基于HTML5 API的拖拽...
  12. MP、OMP与施密特正交化(转载)
  13. 孙玄:微服务架构何去何从?
  14. 飞鸽传书【经典版】(飞鸽传书2011)
  15. php PDO连接mysql
  16. 如何记忆 Spring Bean 的生命周期
  17. 关于新手做ASO的一些方法和技巧
  18. 即时通讯软件:(c++实现)
  19. 链家爬取深圳租房代码(java)
  20. spin_lock_bh想到的一些事

热门文章

  1. TypeScript笔记(5)—— 基本数据类型
  2. axios请求失败重新发起请求_axios请求超时,设置重新请求的完美解决方法
  3. java对日期进行排序_Java对日期时间值的集合进行排序
  4. 2016计算机二级考试c语言真题及答案,计算机二级考试c语言真题_2017计算机二级考试C语言复习题及答案...
  5. springMVC的controller单例和多例下成员变量的问题
  6. ectouch手机商城首页调用指定分类下的商品
  7. UVA 11478(差分约束 + 二分)
  8. android 检测摇一摇
  9. 【Git入门之六】远程仓库
  10. ImageButton 按钮查看商品详细信息