使用数据结构过滤敏感词算法
前缀树
名称: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"
使用数据结构过滤敏感词算法相关推荐
- python过滤敏感词记录
简述: 关于敏感词过滤可以看成是一种文本反垃圾算法,例如 题目:敏感词文本文件 filtered_words.txt,当用户输入敏感词语,则用 星号 * 替换,例如当用户输入「北京是个好城市」,则变成 ...
- C#过滤敏感词DFA算法
今天游戏正好用到需要过滤敏感词将出现的敏感词替换成*,在网上找了许久找了一片可用的java版本的DFA算法,最后费了一番功夫将其思路用C#实现,里面的注释甚至都没改动的,这里直接上代码,这里不借助任何 ...
- IM敏感词算法原理和实现
文章目录 IM敏感词算法原理和实现 字符串查找KMP Trie树 Trie树的基本性质 基础入门 分析与实现 数据结构定义 insert实现 search实现 startsWith实现 敏感词搜索 性 ...
- SpringBoot使用前缀树过滤敏感词
前缀树 Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:利 ...
- php过滤敏感词实例代码
php过滤敏感词实例代码 <?php /** * Created by JetBrains PhpStorm. * User: lsl * Date: 13-8-28 ...
- flex java 全局拦截_flex + java 过滤敏感词
过滤敏感词这个相对比较容易做到,网上也很多方法,看得比较多的一个方法就是:把所有的敏感词写入到一个properties文件中,程序启动时拼成一个正则表达式.这个也只是比较基础的敏感词过滤器,比较强大的 ...
- python过滤敏感词汇_利用Python正则表达式过滤敏感词的方法
利用Python正则表达式过滤敏感词的方法 问题描述:很多网站会对用户发帖内容进行一定的检查,并自动把敏感词修改为特定的字符. 技术要点: 1)Python正则表达式模块re的sub()函数: 2)在 ...
- ios 弹幕过滤敏感词方案对比和性能测试
在看视频的过程中, 很多用户会发弹幕, 当前用户可以设置过滤敏感词和敏感用户, 设置后, 命中敏感词和敏感用户的弹幕就不会显示. 敏感词和敏感用户的设置上限为各100. 由客户端进行过滤, 不区分大 ...
- php敏感字符串过滤_PHP的一个过滤敏感词或脏话的方法
PHP的一个过滤敏感词或脏话的方法 主要使用了 int substr_count ( string haystack, string needle [, int offset [, int leng ...
最新文章
- 关于Python的装饰器(1)
- 关于引用与指针实现多态的一些记录
- LoadRunner的Socket脚本关联小技巧
- 若计算机内存的地址从00H,2003计算机科学导论课程试卷A
- android智能老人机系统,国产老人机也可以变智能!可运行Android
- DataView对象的用法 1207
- 雷锋网2012应用下载排行榜
- 代码质量度量标准_追求代码质量(2): 监视圈复杂度
- 标准BT.656并行数据结构
- 差分输出和单端输出的区别(转载)
- 给Bert加速吧!NLP中的知识蒸馏Distilled BiLSTM论文解读
- ecdf与ksdensity的区别
- mysql文章相似度计算_文章相似度计算
- 图嵌入中节点如何映射到向量
- 【论文】Track to Detect and Segment: An Online Multi-Object Tracker
- 示例填充图片_用示例解释洪水填充算法
- 命名实体如何进行概念消歧?
- vue.js 二级路由/三级路由
- 什么软件可以测试自己的穿衣,心理测试:4个女孩,哪个穿衣风格跟你最像?秒测你的真实性格...
- slxrom+v.21+原生android+4.2,红米4高配版 魔趣OS 安卓10 MagiskV21版 完美ROOT 纯净完美 原生极简 纯净推荐...