JAVA使用前缀树(Tire树)实现敏感词过滤、词典搜索
短信预约 -IT技能 免费直播动态提醒
简介
有时候需要对用户输入的内容进行敏感词过滤,或者实现查找文本中出现的词典中的词,用遍历的方式进行替换或者查找效率非常低,这里提供一个基于Trie树的方式,进行关键词的查找与过滤,在词典比较大的情况下效率非常高。
Trie树
Trie树,又叫前缀树,多说无益,直接看图就明白了
词典:[“猪狗”, “小狗”, “小猫”, “小猪”, “垃圾”, “狗东西”]
Tire数据结构:
code
树节点Node.class
public class Node {
private Map<Character, Node> nextNodes = new HashMap<>();
public void addNext(Character key, Node node){
nextNodes.put(key, node);
}
public Node getNext(Character key){
return nextNodes.get(key);
}
public boolean isLastCharacter(){
return nextNodes.isEmpty();
}
}
搜索类TrieSearcher.class
public class TrieSearcher {
private Node root = new Node();
public void addWord(String word) {
Node tmpNode = root;
for (char c : word.toCharArray()) {
Node node = tmpNode.getNext(c);
if (null == node) {
node = new Node();
tmpNode.addNext(c, node);
}
tmpNode = node;
}
}
public String replace(String text, String afterReplace) {
StringBuilder result = new StringBuilder(text.length());
Node tmpNode = root;
int begin = 0, pos = 0;
while (pos < text.length()) {
char c = text.charAt(pos);
tmpNode = tmpNode.getNext(c);
if (null == tmpNode) {
result.append(text.charAt(begin));
begin++;
pos = begin;
tmpNode = root;
} else if (tmpNode.isLastCharacter()) {
// 匹配完成, 进行替换
result.append(afterReplace);
pos++;
begin = pos;
tmpNode = root;
} else {
// 匹配上向后移
pos++;
}
}
result.append(text.substring(begin));
return result.toString();
}
public Map<String, Integer> find(String text) {
Map<String, Integer> resultMap = new HashMap<>(16);
Node tmpNode = root;
StringBuilder word = new StringBuilder();
int begin = 0, pos = 0;
while (pos < text.length()) {
char c = text.charAt(pos);
tmpNode = tmpNode.getNext(c);
if (null == tmpNode) {
begin++;
pos = begin;
tmpNode = root;
} else if (tmpNode.isLastCharacter()) {
// 匹配完成
String w = word.append(c).toString();
resultMap.put(w, resultMap.getOrDefault(w, 0) + 1);
pos++;
begin = pos;
tmpNode = root;
word = new StringBuilder();
} else {
// 匹配上向后移
word.append(c);
pos++;
}
}
return resultMap;
}
}
测试Main.class
public class Main {
public static void main(String[] args) {
TrieSearcher trieSearcher = new TrieSearcher();
Stream.of("猪狗", "小狗", "小猫", "小猪", "垃圾", "狗东西").forEach(trieSearcher::addWord);
String sentence = "你好,小狗,小猪,今天天气真好。";
System.out.println(trieSearcher.replace(sentence, "***"));
System.out.println(trieSearcher.find(sentence));
}
}
输出:
你好,***,***,今天天气真好。
{小猪=1, 小狗=1}
Benchmark:
replace 1093.517 ns/op
trie 200.042 ns/op
结论
在仅有短文本和小词典的情况下,通过性能测试可以看出前缀树的效率很高,随着文本和词典的增长,性能提升会非常明显。
到此这篇关于JAVA使用前缀树(Tire树)实现敏感词过滤、词典搜索的文章就介绍到这了,更多相关JAVA前缀树敏感词过滤内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341