赞
踩
在计算机科学中,trie树,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。
trie中的键通常是字符串,但也可以是其它的结构。trie的算法可以很容易地修改为处理其它结构的有序序列,比如一串数字或者形状的排列。比如,bitwise trie中的键是一串位元,可以用于表示整数或者内存地址
可以最大限度地减少无谓的字符串比较
跟哈希表比较:
1. 最坏情况时间复杂度比hash表好
2. 没有冲突,除非一个key对应多个值(除key外的其他信息)
3. 自带排序功能(类似Radix Sort),中序遍历trie可以得到排序。
虽然不同单词共享前缀,但其实trie是一个以空间换时间的算法。其每一个字符都可能包含至多字符集大小数目的指针(不包含卫星数据)。
每个结点的子树的根节点的组织方式有几种。
如果数据存储在外部存储器等较慢位置,Trie会较hash速度慢(hash访问O(1)次外存,Trie访问O(树高))。
假设我们的敏感词库有下面敏感词:
高清AV
日狗
高清裸体图
静态代码块:执行优先级高于非静态的初始化块,它会在类初始化的时候执行一次,执行完成便销毁,它仅能初始化类变量,即static修饰的数据成员。
static{
}
但是一般我们的敏感词词库都很大,当敏感词数量很多之后我们新添敏感词的时候可能会忘记之前是不是添加了某个敏感词,那就会出现重复的敏感词,为了敏感词树构建的效率,我们要对敏感词去重
怎么去重?很简单,把敏感词读出来之后放进HashSet中,再把敏感词从HashSet中遍历出来插入TRIE树就可以啦
如果有一段文字是:那些简单就是不肯免费带你吃鸡充不上电剧场版免费吃鸡,带你看免*费 AV
怎么从上面这段文字中检测出这段文字是否包含敏感词呢?
有时候用户知道我们有敏感词检测的功能,会用一些特殊符号隔开敏感词,这时候为了更严格地检测,我们要把用户输入的特殊字符去掉特殊字符再检测
/** * create by: Antares * description: 去掉特殊字符 * create time: 2020/6/9 18:22 * return **/ public static String deleteSpecialWord (String txt) { String regEx = "[\n`~!@#$%^&*()+=|{}':;,\\[\\].<>/?!¥…()—【】‘;:”“’。,_·、?]"; //可以在中括号内加上任何想要替换的字符,实际上是一个正则表达式 //这里是将特殊字符换为aa字符串,""代表直接去掉 String aa = ""; Pattern p = Pattern.compile (regEx); Matcher m = p.matcher (txt);//这里把想要替换的字符串传进来 return m.replaceAll (aa).trim (); }
有时候会出现一种情况是:词库中含有敏感词是另一个敏感词的前缀,比如:abc是敏感词,abcd也是敏感词,检测ABCD很好办,因为可以默认为叶子结点就是结束位置
那么如何能够在检测时检测出abc呢?
那么在JAVA中选用什么数据结构来实现Trie树呢
HashMap
import org.springframework.core.io.ClassPathResource; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.*; public class SensitiveWordInit { public static HashMap sensitiveWordMap; private static String ENCODING = "UTF-8"; //字符编码 static { initKeyWord (); } public SensitiveWordInit () { super (); } public static Map initKeyWord () { try { //读取敏感词库 Set<String> keyWordSet = readSensitiveWordFile (); // System.out.println (keyWordSet.size ()); //将敏感词库加入到HashMap中
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。