前缀树

名称:Tire、字典树、查找树

特点:查找效率高,消耗内存大

应用:字符串检索、词频统计、字符串排序等

敏感词过滤器

定义前缀树

package com.nowcoder.community.util;import org.springframework.stereotype.Component;import java.util.HashMap;
import java.util.Map;@Component
public class SensitiveFilter {//描述前缀树的每一个节点private class TrieNode{//关键词结束标识private boolean isKeywordEnd=false;//当前节点的子节点(key是下级节点的字符,value是下级)                                                          ·   999999private Map<Character,TrieNode> subModes=new HashMap<>();public boolean isKeywordEnd() {return isKeywordEnd;}public void setKeywordEnd(boolean keywordEnd) {isKeywordEnd = keywordEnd;}//添加子节点的方法public void addSubNode(Character c,TrieNode node){subModes.put(c,node);}//获取子节点public TrieNode getSubNode(Character c){return subModes.get(c);}}
}

根据敏感词,初始化前缀树

在sensitive.words.txt文件中一行定义一个敏感词

    private static final Logger logger = LoggerFactory.getLogger(SensitiveFilter.class);//替换符private static final String REPLACEMENT="***";//初始化根节点private TrieNode rootNode=new TrieNode();@PostConstruct//在服务启动的时候会初始化这个方法,解决了只需要初始化一次的问题public void init(){try(        InputStream is= this.getClass().getClassLoader().getResourceAsStream("sensitive-words.txt");BufferedReader reader=new BufferedReader(new InputStreamReader(is));){//读取每一个敏感词String keyword;while ((keyword=reader.readLine())!=null){//添加到前缀树this.addKeyWord(keyword);}}catch (IOException e){logger.error("加载敏感词文件失败"+e.getMessage());}}//将一个敏感词添加到前缀树当中private void addKeyWord(String keyword){TrieNode tempNode=rootNode;for(int i=0;i<keyword.length();i++){char c=keyword.charAt(i);TrieNode subNode=tempNode.getSubNode(c);if(subNode==null){//初始化子节点subNode=new TrieNode();tempNode.addSubNode(c,subNode);}//让指针指向子节点,进入下一轮循环tempNode=subNode;//设置结束标识if(i==keyword.length()-1){tempNode.setKeywordEnd(true);}}}

编写过滤敏感词的方法

 /*** 过滤敏感词* @param text 待过滤的文本* @return 过滤后的文本*/public String filter(String text){if(StringUtils.isBlank(text)){return null;}//指针1TrieNode tempNode=rootNode;//指针2int begin=0;//指针3int position=0;//结果StringBuilder sb=new StringBuilder();while (position<text.length()){char c=text.charAt(position);//跳过符号if(isSymbol(c)){//若指针1指向根节点,将此符号计入结果,让指针2向下走一步if(tempNode==rootNode){sb.append(c);begin++;}//无论符号在开头或中间,指针3都向下走一步position++;continue;}//检查下级节点tempNode= tempNode.getSubNode(c);if(tempNode==null){//以begin开头的字符串不是敏感词sb.append(text.charAt(begin));//进入下一个位置position=++begin;//重新指向根节点tempNode=rootNode;}else if(tempNode.isKeywordEnd()){//发现敏感词,将begin-position字符串替换掉sb.append(REPLACEMENT);//进入下一个位置begin=++position;//重新指向根节点tempNode=rootNode;}else {//检查下一个字符position++;}}//将最后一批字符计入结果sb.append(text.substring(begin));return sb.toString();}//判断是否为符号private boolean isSymbol(Character c){//0x2E80-0x9FFF是东亚文字范围return !CharUtils.isAsciiAlphanumeric(c)&&(c<0x2E80||c>0x9FFF);}

测试

package com.nowcoder.community;import com.nowcoder.community.util.SensitiveFilter;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class SensitiveTest {@Autowiredprivate SensitiveFilter sensitiveFilter;@Testpublic void testSensitiveFilter(){String text="这里可以赌※博,可以嫖娼,哈哈哈";System.out.println(sensitiveFilter.filter(text));}
}

原理

检测目标以字符为单位

根据敏感词初始化前缀树,根节点为root,根据每个敏感词的字符来添加节点,将末节点进行标记。给定一个字符串“xwabfabcff”来过滤敏感词abc、bf、be,需要三个指针,指针1指向前缀树,指针2、指针3指向字符串,默认初始指针1指向root,指针2、3指向字符串的起始端。当过滤开始,指针2首先会停在x,然后指针1判断前缀树是否有x的起点,判断不是不需要过滤x,指针2会向后移动一位到w,随之指针3也会向后移动一位,类似判断没有w开始的敏感词不需要过滤w,指针2和3向后移动一位到a,指针1进行判断有a为起始端的树,然后指针2会停在a,指针3往后移动一位到b,指针1也会向下查看a下节点是否有b,判断有,但是没有到达末节点,指针3会继续向后移动,到f,指针1会在b在查看是否有f,判断没有不需要过滤a,指针2会移动到b,指针3也会回到指针2的位置,类似的判断bf是敏感词,会将其过滤为***代替,最终的字符串后过滤为"xwa*****ff"

使用数据结构过滤敏感词算法相关推荐

  1. python过滤敏感词记录

    简述: 关于敏感词过滤可以看成是一种文本反垃圾算法,例如 题目:敏感词文本文件 filtered_words.txt,当用户输入敏感词语,则用 星号 * 替换,例如当用户输入「北京是个好城市」,则变成 ...

  2. C#过滤敏感词DFA算法

    今天游戏正好用到需要过滤敏感词将出现的敏感词替换成*,在网上找了许久找了一片可用的java版本的DFA算法,最后费了一番功夫将其思路用C#实现,里面的注释甚至都没改动的,这里直接上代码,这里不借助任何 ...

  3. IM敏感词算法原理和实现

    文章目录 IM敏感词算法原理和实现 字符串查找KMP Trie树 Trie树的基本性质 基础入门 分析与实现 数据结构定义 insert实现 search实现 startsWith实现 敏感词搜索 性 ...

  4. SpringBoot使用前缀树过滤敏感词

    前缀树 Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:利 ...

  5. php过滤敏感词实例代码

    php过滤敏感词实例代码 <?php   /**     * Created by JetBrains PhpStorm.     * User: lsl     * Date: 13-8-28 ...

  6. flex java 全局拦截_flex + java 过滤敏感词

    过滤敏感词这个相对比较容易做到,网上也很多方法,看得比较多的一个方法就是:把所有的敏感词写入到一个properties文件中,程序启动时拼成一个正则表达式.这个也只是比较基础的敏感词过滤器,比较强大的 ...

  7. python过滤敏感词汇_利用Python正则表达式过滤敏感词的方法

    利用Python正则表达式过滤敏感词的方法 问题描述:很多网站会对用户发帖内容进行一定的检查,并自动把敏感词修改为特定的字符. 技术要点: 1)Python正则表达式模块re的sub()函数: 2)在 ...

  8. ios 弹幕过滤敏感词方案对比和性能测试

    在看视频的过程中, 很多用户会发弹幕, 当前用户可以设置过滤敏感词和敏感用户,  设置后, 命中敏感词和敏感用户的弹幕就不会显示. 敏感词和敏感用户的设置上限为各100. 由客户端进行过滤, 不区分大 ...

  9. php敏感字符串过滤_PHP的一个过滤敏感词或脏话的方法

    PHP的一个过滤敏感词或脏话的方法 主要使用了  int substr_count ( string haystack, string needle [, int offset [, int leng ...

最新文章

  1. 关于Python的装饰器(1)
  2. 关于引用与指针实现多态的一些记录
  3. LoadRunner的Socket脚本关联小技巧
  4. 若计算机内存的地址从00H,2003计算机科学导论课程试卷A
  5. android智能老人机系统,国产老人机也可以变智能!可运行Android
  6. DataView对象的用法 1207
  7. 雷锋网2012应用下载排行榜
  8. 代码质量度量标准_追求代码质量(2): 监视圈复杂度
  9. 标准BT.656并行数据结构
  10. 差分输出和单端输出的区别(转载)
  11. 给Bert加速吧!NLP中的知识蒸馏Distilled BiLSTM论文解读
  12. ecdf与ksdensity的区别
  13. mysql文章相似度计算_文章相似度计算
  14. 图嵌入中节点如何映射到向量
  15. 【论文】Track to Detect and Segment: An Online Multi-Object Tracker
  16. 示例填充图片_用示例解释洪水填充算法
  17. 命名实体如何进行概念消歧?
  18. vue.js 二级路由/三级路由
  19. 什么软件可以测试自己的穿衣,心理测试:4个女孩,哪个穿衣风格跟你最像?秒测你的真实性格...
  20. slxrom+v.21+原生android+4.2,红米4高配版 魔趣OS 安卓10 MagiskV21版 完美ROOT 纯净完美 原生极简 纯净推荐...

热门文章

  1. 电动汽车典型危险工况及安全检验探讨 | 机动车登记查验
  2. e4x java_application.e4xmi
  3. 微博同城热搜抓取逻辑(333城市)
  4. 中国长超细纤维市场趋势报告、技术动态创新及市场预测
  5. MFC使用sleep函数注意事项
  6. 如何更改手机Android版本,安卓手机怎么刷机 教你刷成其他版本系统【详细介绍】...
  7. Android logd日志原理
  8. 用免费GPG加密收发Email
  9. 关于Alpha Matte 和 Luma Matte
  10. VSCode不同窗口设置不同颜色