【数据结构与算法】DFA算法-关键词匹配-java案例实现

该算法往往是用于匹配一些敏感词、绝对词等,从一篇文章中快速找到其中包含的关键词。

实现思路

        先读取所有关键词并存入set集合中。再将set中的关键词存入HashMap中,是以每个关键词字顺序存储,key为一个字、value为一个HashMap。在每一个HashMap都有一个key为is_end键值对来代表该字之前是否为一个关键词。

 大致存储结构如下: 

        以此为例(最先、最先进、最先进科技、最先进工艺、全球、全国)

 

首先存储这些关键词

/**
 * @author CC
 * @version 1.0
 * @since2023/11/7
 */
public  class SensitiveWordMap {
    private static final String ENCODING = "utf-8";

    public static final String IS_END_KEY ="is_end";

    // 初始化敏感字库
    public Map initKeyWord() throws IOException {
        Set<String> set = readSensitiveWordFile();
        Map<String, Object> stringObjectMap = addSensitiveWordToHashMap(set);
        return stringObjectMap;
    }

    // 读取敏感词库,存入Set中
    private   Set<String> readSensitiveWordFile() throws IOException {
        Set<String> wordSet =null;
        //通过txt文件获取所有关键词并存入set集合中
        try (InputStream inputStream = SensitiveWordMap.class.getResourceAsStream("/static/words.txt");
             InputStreamReader inputStreamReader = new InputStreamReader(inputStream, ENCODING);
             BufferedReader bufferedReader = new BufferedReader(inputStreamReader);) {
            wordSet =new HashSet<String>();
            String line =null;
            while ((line=bufferedReader.readLine())!=null){
                wordSet.add(line);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return wordSet;
    }

    // 将Set中的敏感词,存入HashMap中
    private Map<String, Object> addSensitiveWordToHashMap(Set<String> wordSet) {

        //初始化词库Map
        Map<String,Object> wordMap =new HashMap<>();

        //遍历关键词库中的每个关键词
        for (String word:wordSet){
            Map<String, Object> nowMap =wordMap;
            //遍历每个关键词的每个字
            for (int i = 0; i <word.length() ; i++) {
                //关键词中的某个字
                String keyChar =String.valueOf(word.charAt(i));
                Map<String,Object> subWordMap = (Map<String, Object>) nowMap.get(keyChar);
                if (subWordMap==null){
                    subWordMap=new HashMap<>();
                    subWordMap.put(IS_END_KEY,false);
                    nowMap.put(keyChar,subWordMap);
                }
                //切换下一层
                nowMap=subWordMap;

                //判断当前“字”是否是关键词的最后一个字
                if (i==word.length()-1){
                    nowMap.put(IS_END_KEY,true);
                }
            }
        }
        return wordMap;
    }
}

words.txt如下 

最佳
最具
最爱
最佳
最优
最优秀
最大
最大程度
最高
最高级
最高档
最高阶
最奢侈
最低
最低级
最低价
最先
最先进
最先进科技
最先进工艺
最先享受
最新
最新科技
最新理念

匹配关键词类

/**
 * @author CC
 * @version 1.0
 * @since2023/11/7
 */
public class SensitiveFilter {

    /**
     * 敏感词过滤器:利用DFA算法 进行敏感词过滤
     */
    private Map sensitiveWordMap = null;

    /**
     * 最小匹配规则,
     * 例如:敏感词库["最先","最先进","最先进工艺"],
     * 语句:"机身采用最先进工艺打造",
     * 匹配结果:[最先]
     */
    public static final int MIN_MATCH_TYPE = 1;

    /**
     * 最大匹配规则,
     * 例如:敏感词库["最先","最先进","最先进工艺"],
     * 语句:"机身采用最先进工艺打造",
     * 匹配结果:[最先进工艺]
     */
    public static final int MAX_MATCH_TYPE = 2;

    // 单例
    private static SensitiveFilter instance = null;

    /**
     * 构造函数,初始化敏感词库
     */
    private SensitiveFilter() throws IOException {
        SensitiveWordMap wordMap = new SensitiveWordMap();
        sensitiveWordMap = wordMap.initKeyWord();
    }

    /**
     * 获取单例
     */
    public static SensitiveFilter getInstance() throws IOException {
        if (instance == null) {
            instance = new SensitiveFilter();
        }
        return instance;
    }

    /**
     * 获取文字中的敏感词
     */
    public Set<String> getSensitiveWord(String txt, int matchType) {
        Set<String> set =new HashSet<>();
        for (int i = 0; i <txt.length() ; i++) {
            int count = checkSensitiveWord(txt, i, matchType);
            if (count!=0){
                set.add(txt.substring(i,count+i));
                i=i+count-1;
            }
        }
        return set;
    }

    /**
     * 检查文字中是否包含敏感字符,检查规则如下:
     * 如果存在,则返回敏感词字符的长度
     * 如果不存在,返回0
     */
    private int checkSensitiveWord(String txt, int beginIndex, int matchType) {
        //关键词库
        Map<String, Object> nowMap = sensitiveWordMap;
        //记录匹配标志次数
        int matchFlag = 0;
        //结束标志
        boolean flag = false;

        //从指定位置开始遍历“关键字“字符串
        for (int i = beginIndex; i < txt.length(); i++) {

            //获取一个字
            String keyChar = String.valueOf(txt.charAt(i));

            //根据当前关键”字“,从词库中获取该”关键字“对应的map
            nowMap = (Map<String, Object>) nowMap.get(keyChar);

            if (nowMap != null) {
                //匹配成功
                matchFlag++;
                if ((boolean) nowMap.get(SensitiveWordMap.IS_END_KEY)) {
                    //代表本次匹配状态终止
                    flag = true;

                    //如果匹配规则是最小匹配,结束匹配过程
                    if (matchType == MIN_MATCH_TYPE) {
                        break;
                    }
                }
            } else {
                //匹配失败
                break;
            }
        }

        //没有匹配结果:匹配字数少于2 或者 匹配没有结束
        if (matchFlag < 2 || !flag) {
            matchFlag = 0;
        }

        return matchFlag;
    }
}

 测试

/**
 * @author CC
 * @version 1.0
 * @since2023/11/7
 */
public class test {
    public static void main(String[] args) throws IOException {
        SensitiveFilter sensitiveFilter = SensitiveFilter.getInstance();
        String txt ="整个机身采用最先进工艺进行制造,是整个东半球最优秀产品,最大程度还原科技震撼!做出最奢侈的产品是终身的信念!";
        Set<String> sensitiveWord = sensitiveFilter.getSensitiveWord(txt, SensitiveFilter.MAX_MATCH_TYPE);
        System.out.println(sensitiveWord);
    }
}

最大匹配规则结果

最小匹配规则结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/129906.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Laplacian Redecomposition for Multimodal Medical Image Fusion

LRD方法 GDIE means ‘gradient-domain image enhancement’&#xff0c;DGR means ‘decision graph redecomposition’ MLD means ‘maximum local difference’ LEM means ‘local energy maximum’&#xff0c;OD means ‘overlapping domain’&#xff0c;LP means ‘L…

Awesome-Selfhosted:互联网常见服务开源平替 | 开源日报 No.68

awesome-selfhosted/awesome-selfhosted Stars: 137.7k License: NOASSERTION Awesome-Selfhosted 是一个列出了可以在自己的服务器上托管的免费软件网络服务和 Web 应用程序列表。 以下是该项目的主要功能&#xff1a; 提供各种类型 (如分析、备份、博客平台等) 的开源软件…

Vue创建浅层响应式数据

shallowReactive&#xff1a;只处理对象第一层数据的响应式&#xff08;浅响应式&#xff09;。 shallowRef&#xff1a;只处理基本数据类型的响应式&#xff0c;不处理对象类型的响应式。 shallowReactive 适用于&#xff1a;如果有一个对象类型的数据&#xff0c;结构比较深…

SQL表、字段、查询参数获取

SQL工具类表、字段、查询参数提取 1. 执行效果2. 使用2.1 引入依赖2.2 相关实体2.3 工具类 1. 执行效果 2. 使用 2.1 引入依赖 <!-- sql 解析处理--><dependency><groupId>com.github.jsqlparser</groupId><artifactId>jsqlparser</artifact…

PLSQL工具 数据库连接名的设置

在help >>surpost info 能看到 这东西好难用啊。。不直接显示url,非要搞个名称。。

2023年A股借壳上市研究报告

第一章 借壳上市概况 1.1 定义 借壳上市作为一种独特的资本市场操作手法&#xff0c;历来是企业拓展融资渠道和实现市场战略目标的重要途径。具体来说&#xff0c;借壳上市可分为狭义与广义两种模式。在狭义的定义下&#xff0c;借壳上市是指一家已上市的公司的控股母公司&am…

React【异步逻辑createAsyncThunk(一)、createAsyncThunk(二)、性能优化、createSelector】(十二)

文章目录 异步逻辑 createAsyncThunk&#xff08;一&#xff09; createAsyncThunk&#xff08;二&#xff09; 性能优化 createSelector 异步逻辑 //Product.js const onAdd () > {const name nameRef.current.value// 触发添加商品的事件dispatch(addProduct({name…

vue3介绍

介绍 3完全兼容2的语法 vue3&#xff1a;体积更小&#xff0c;性能会更高。底层做了很多优化 2倍左右 vue3vitets 渐进式框架 vue3和vue2 的区别 新语法&#xff0c;性能上提升很多 思想是一致的&#xff1a;动态绑定&#xff1a;状态data&计算属性&#xff0c;监听某些状态…

超声波俱乐部分享:Enter AI native application

11月5日&#xff0c;2023年第十四期超声波俱乐部内部分享会在北京望京举行。本期的主题是&#xff1a;Enter AI native application。 到场的嘉宾有&#xff1a;超声波创始人杨子超&#xff0c;超声波联合创始人、和牛商业创始人刘思雨&#xff0c;蓝驰创投合伙人刘勇&#xf…

The Sandbox于香港举办全球首个创作者日,推出「公开发布」功能,并为 GameMakerFund提供1亿$SAND基金!

新的 NFT 铸造、无需编码的 Game Maker 软件升级、其他支持 Web3 创作者的功能优化。 2023 年 11 月 3 日——The Sandbox 举办了首届全球创作者日活动&#xff0c;并在活动期间宣布了其在 2024 年的计划&#xff0c;包括为创作者赋能&#xff0c;在地图上呈现 2000 个用户生成…

说说 React中的setState执行机制

一、是什么 一个组件的显示形态可以由数据状态和外部参数所决定&#xff0c;而数据状态就是state 当需要修改里面的值的状态需要通过调用setState来改变&#xff0c;从而达到更新组件内部数据的作用 如下例子&#xff1a; import React, { Component } from react export d…

flutter 使用 hive 遇到的错误

1. ] Unhandled Exception: RangeError: Not enough bytes available. 根据日志定位到 下图的地方 解决&#xff1a;因为之前存在保存到本地的信息&#xff0c;但是你修改了 数据类里面的东西&#xff08;比如添加变量啥的&#xff09;&#xff0c;清空app缓存或者卸载重新构…

vue2和vue3 的双向绑定原理

前文: 都知道vue是双向绑定的mvvm框架,也一直再用,那么他到底是如何实现的呢?vue3又针对这点做了哪些升级呢? 这段时间也正好有空,下面我们来一起看看吧 一 、vue的双向绑定原理 那么什么是双向绑定呢 ? 一般我们所指的双向绑定都是指的数据,即当数据发生变化的时候,视图也…

Vue简单使用Echart图表柱形图 vue使用柱形图 vue使用 echart图表柱形图 vue使用柱形图

Vue简单使用Echart图表柱形图 vue使用柱形图 vue使用 echart图表柱形图 vue使用柱形图 1、安装依赖2、页面Demo使用3、效果图 1、安装依赖 官方文档&#xff1a;https://echarts.apache.org/zh/option.html#title 官方在线示例&#xff1a;https://echarts.apache.org/exampl…

SpringCloudAlibaba——Nacos

Nacos是服务注册中心服务配置中心。替换了以前的EurekaConfigBus。 1.Nacos作为服务注册中心 Nacos支持AP和CP模式的转换。 2.Nacos作为服务配置中心 服务要配置两个yml文件&#xff0c;bootstrap.yml和application.yml。因为Nacos同springcloud-config一样&#xff0c;在项…

4S店汽车行业万能通用小程序源码系统 在线预约试驾+购车计算器 源码完全开源可二次开发

随着互联网技术的发展和普及&#xff0c;越来越多的消费者开始依赖于互联网进行消费。传统的汽车销售模式也正在经历着数字化转型&#xff0c;以适应消费者需求的变化。这款小程序源码系统就是为帮助汽车4S店等销售商实现数字化转型而开发的。 以下是部分核心功能的代码模块&a…

OushuDB 专家认证第四期报名开始啦!

OushuDB 专家认证培训第四期今日正式启动&#xff01;本次培训为偶数科技面向生态合作伙伴与客户公开举办的线上培训&#xff0c;旨在共同发展 OushuDB 生态。 报名时间&#xff1a;2023年11月9日9:00—11月30日12:00 报名方式&#xff1a;偶数科技官网&#xff08;点击下方阅…

新“芯”向荣|利用合作科研设计和优化电芯案例探究

利用合作科研设计和优化电芯 锂电行业发展的契机——我国致力于减少二氧化碳的排放&#xff0c;将2050年实现净零排放作为目标。 电池制造商、细分领域专用电芯设计厂商、汽车OEM厂商、电动垂直起降(eVTOL)飞机制造商以及电池材料供应商都投入了大量的资源&#xff0c;寻求电…

金融服务行业如何面对精细化的大数据模式下日益增加的文件传输压力?

随着数字化转型的加速&#xff0c;金融机构需要在数据化基础上进行升级和转型&#xff0c;挖掘互联网数据传输与金融业深度融合的新形态&#xff0c;同时确定如何更好地存储、保护和分析数据。然而&#xff0c;在精细化的大数据模式下&#xff0c;金融机构也面临着日益增加的数…

ChatGPT 上新,效果炸裂,知识平台才是大模型的最佳狩猎场

数新网络_让每个人享受数据的价值浙江数新网络有限公司是一家开源开放、专注于云数据智能操作系统和数据价值流通的服务商。公司自主研发的DataCyber云数据智能操作系统&#xff0c;主要包括数据平台CyberData、人工智能平台CyberAI、数据智能引擎CyberEngine、数据安全平台Cyb…