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前缀树敏感词过滤内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot2 整合FreeMarker实现页面静态化示例详解

    SpringBoot2 整合FreeMarker实现页面静态化示例详解

    这篇文章主要介绍了SpringBoot2 整合FreeMarker实现页面静态化示例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • Java JVM虚拟机调优详解

    Java JVM虚拟机调优详解

    JVM是JavaVirtualMachine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的,本文主要介绍了jvm调优,感兴趣的小伙伴们可以参考一下<BR>
    2022-07-07
  • SpringBoot集成WebSocket实现后台向前端推送信息的示例

    SpringBoot集成WebSocket实现后台向前端推送信息的示例

    这篇文章主要介绍了SpringBoot集成WebSocket实现后台向前端推送信息的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • SpringBoot Application核心注解详解

    SpringBoot Application核心注解详解

    进入到@SpringBootApplication的源码,可以看到里面组合了三个我们感兴趣的注解@ComponentScan、@EnableAutoConfiguration、@SpringBootConfiguration,我们一一分析这三个注解
    2022-10-10
  • SpringBoot整合Spring Security过滤器链加载执行流程源码分析(最新推荐)

    SpringBoot整合Spring Security过滤器链加载执行流程源码分析(最新推荐)

    Spring Boot 对于 Spring Security 提供了自动化配置方案,可以使用更少的配置来使用 Spring Security,这篇文章主要介绍了SpringBoot整合Spring Security过滤器链加载执行流程源码分析,需要的朋友可以参考下
    2023-02-02
  • java 如何往已经存在的excel表格里面追加数据的方法

    java 如何往已经存在的excel表格里面追加数据的方法

    这篇文章主要介绍了java 如何往已经存在的excel表格里面追加数据的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • Spring session 获取当前账户登录数的实例代码

    Spring session 获取当前账户登录数的实例代码

    这篇文章主要介绍了Spring session 获取当前账户登录数,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • SpringBoot结合Neo4j自定义cypherSql的方法

    SpringBoot结合Neo4j自定义cypherSql的方法

    这篇文章主要介绍了SpringBoot结合Neo4j自定义cypherSql,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-11-11
  • java线程组构造方法源码解析

    java线程组构造方法源码解析

    这篇文章主要为大家介绍了java线程组构造方法源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • java实现科研信息管理系统

    java实现科研信息管理系统

    这篇文章主要为大家详细介绍了java科研信息管理系统,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02

最新评论