JAVA使用前缀树(Tire树)实现敏感词过滤、词典搜索

 更新时间:2023年01月03日 10:31:36   作者:萌萌哒二狗子  
本文主要介绍了JAVA使用前缀树(Tire树)实现敏感词过滤、词典搜索,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

简介

有时候需要对用户输入的内容进行敏感词过滤,或者实现查找文本中出现的词典中的词,用遍历的方式进行替换或者查找效率非常低,这里提供一个基于Trie树的方式,进行关键词的查找与过滤,在词典比较大的情况下效率非常高。

Trie树

Trie树,又叫前缀树,多说无益,直接看图就明白了

词典:[“猪狗”, “小狗”, “小猫”, “小猪”, “垃圾”, “狗东西”]

Tire数据结构:

在这里插入图片描述

code

树节点Node.class

/**
 * trie tree
 *
 * @author lovely dog
 * @date 2020/10/20
 */
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

/**
 * trie tree searcher
 *
 * @author lovely dog
 * @date 2020/10/20
 */
public class TrieSearcher {

    private Node root = new Node();

    /**
     * 添加词
     *
     * @param word 词
     */
    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;
        }
    }

    /**
     * 替换词
     *
     * @param text         待处理文本
     * @param afterReplace 替换后的词
     * @return 处理后的文本
     */
    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();
    }

    /**
     * 查找
     *
     * @param text 待处理文本
     * @return 统计数据 key: word value: count
     */
    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前缀树敏感词过滤内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 值得Java程序猿阅读的书籍

    值得Java程序猿阅读的书籍

    这篇文章主要推荐了一些值得Java程序猿阅读的书籍,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • java容器类知识点详细总结

    java容器类知识点详细总结

    这篇文章主要介绍了java容器类知识点详细总结,
    2019-06-06
  • Java编程中正则表达式的用法总结

    Java编程中正则表达式的用法总结

    这篇文章主要介绍了Java编程中正则表达式的用法总结,正则表达式是一种强大的字符串处理工具,Java对正则表达式的支持还是很不错的,我们先来整理一下正则表达式的一些基础知识:
    2016-05-05
  • 详解Spring Boot的GenericApplicationContext使用教程

    详解Spring Boot的GenericApplicationContext使用教程

    这篇教程展示了如何在Spring应用程序中使用GenericApplicationContext 。小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-11-11
  • Java实现跳跃表的示例详解

    Java实现跳跃表的示例详解

    跳表全称叫做跳跃表,简称跳表,是一个随机化的数据结构,实质就是一种可以进行二分查找的有序链表。本文将利用Java语言编写一个跳表,需要的可以参考一下
    2022-05-05
  • java实现快速排序的方法

    java实现快速排序的方法

    这篇文章主要介绍了java实现快速排序的方法,涉及java排序的相关操作技巧,需要的朋友可以参考下
    2015-05-05
  • java压缩zip文件中文乱码问题解决方法

    java压缩zip文件中文乱码问题解决方法

    这篇文章主要介绍了java压缩zip文件中文乱码问题的解决方法,需要的朋友可以参考下
    2014-07-07
  • Java 如何使用@Autowired注解自动注入bean

    Java 如何使用@Autowired注解自动注入bean

    这篇文章主要介绍了Java 使用@Autowired注解自动注入bean的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • OpenFeign无法远程调用问题及解决

    OpenFeign无法远程调用问题及解决

    文章介绍了在使用Feign客户端时遇到的读超时问题,并分析了原因是系统启动时未先加载Nacos配置,为了解决这个问题,建议将Nacos配置放在`bootstrap.yml`文件中,以便项目启动时优先加载Nacos配置
    2024-11-11
  • java 中锁的性能提高办法

    java 中锁的性能提高办法

    这篇文章主要介绍了java 中锁的性能提高办法的相关资料,需要的朋友可以参考下
    2017-02-02

最新评论