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

news2024/11/24 0:37:31

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

实现思路

        先读取所有关键词并存入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.coloradmin.cn/o/1187262.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器视觉人体跌倒检测系统 - opencv python 计算机竞赛

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 机器视觉人体跌倒检测系统 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&…

frida hook(深入浅出)

Andrax搭建Android渗透测试环境 编译官方frida源码 APP基于Frida脱壳 Frida Hook的使用方法 Frida逆向分析APP实战 魔改frida到绕过检测的思路 配置fridaserver为后台进程 使用frida-net玩转frida-rpc 内置frida hook到Android系统 内置frida-inject工具到手机系统 三…

I/O控制器

一、概述 I/O设备管理-机械部件(I/O硬件设备)电子部件(I/O控制器)接口(设备与控制器间通信媒介) 二、组成 各寄存器间的编址方式&#xff1a; 三、控制方式 1.轮询程序控制 2.中断程序控制 3.直接存储器访问(DMA)

漏刻有时百度地图API实战开发(3)自动获取地图多边形中心点坐标

在百度地图中&#xff0c;多边形覆盖物表示地图上的多边形区域。这些区域可以是封闭的&#xff0c;也可以是开放的。多边形覆盖物通常用于表示地图上的行政区划、地标或任何需要强调的区域。 多边形覆盖物拥有自己的地理坐标&#xff0c;并能随着地图的拖动或缩放而相应地移动…

2023最新最全【Adobe After Effection 2023】下载安装零基础教程【附安装包】

AE2023下载点这里 教学 1.鼠标右击【Ae2023(64bit)】压缩包选择&#xff08;win11系统需先点击“显示更多选项”&#xff09;【解压到 Ae2023(64bit)】。 2.打开解压后的文件夹&#xff0c;鼠标右击【Set-up】选择【以管理员身份运行】。 3.点击【文件夹图标】&#xff0c;…

Scala爬虫如何实时采集天气数据?

这是一个基本的Scala爬虫程序&#xff0c;使用了Scala的http library来发送HTTP请求和获取网页内容。在爬取天气预报信息时&#xff0c;我们首先需要创建一个代理对象proxy&#xff0c;并将其用于发送HTTP请求。然后&#xff0c;我们使用http库的GET方法获取网页内容&#xff0…

Leetcode-LCR 021 删除链表的倒数第 N 个结点

快慢指针&#xff0c;快指针先移动n-1个节点后&#xff0c;慢指针从虚拟头结点出发&#xff08;相当于快慢指针相隔n个节点&#xff09;&#xff0c;快慢指针一起向链表尾依次移动一个结点&#xff0c;当快指针移动到表位时&#xff0c;慢指针正好移到被删除元素的前一个结点&a…

扭矩传感器采用一阶RC滤波

扭矩传感器内部的一阶RC&#xff08;电阻-电容&#xff09;滤波器是一种用于滤除高频噪声和干扰的电路&#xff0c;以确保传感器输出的信号平滑和稳定。这种滤波器通常用于传感器输出信号的处理&#xff0c;以减少测量中的高频噪声。 一阶RC滤波器通常由一个电阻&#xff08;R…

AM5-DB低压备自投装置在河北冠益荣信科技公司洞庭变电站工程中的应用

叶根胜 安科瑞电气股份有限公司 上海嘉定 201800 摘 要&#xff1a;随着电力需求的增加&#xff0c;电力系统对供电可靠性的要求越来越高&#xff0c;许多供电系统已经有两条或两条以上的供电线路。备用电源自动输入装置可有效提高供电可靠性&#xff0c;工作电源故障断开后可…

三菱FX3U系列—原点回归指令

目录 一、简介 二、指令形式 1、原点指令[ZRN/DZRN] 2、带搜索的原点回归指令[DSZR] 三、回归指令运行过程 1、ZRN原点回归运行过程 2、带搜索的原点回归运行过程 四、特殊辅助继电器 五、特殊输出模块 六、总结 一、简介 用于将电机或伺服驱动器控制的轴回到预定的原…

PHP利用jsonp跨域实现

JSONP&#xff08;JSON with Padding&#xff09;是一种使用普通的<script>标签来发起跨域请求的方法。JSONP利用了HTML页面可以直接引入外部JavaScript文件而不受同源策略限制的特性 实现效果 1、实现代码中php文件 <?php // 接收GET请求参数 $param $_GET[callb…

2023年双11有哪些便宜的云服务器值得推荐?

每年的双11期间各大云计算服务商都会推出特价云服务器&#xff0c;今年自然也不例外&#xff0c;下面给大家分享2023年双11有哪些便宜的云服务器值得推荐。 1、阿里云【传送门>>>】 阿里云双11推出了金秋云创季活动&#xff0c;2核2G3M不限流量&#xff0c;1年99元&…

springboot中如何同时操作同一功能

问题描述 测试阶段&#xff0c;由于存在某一功能的同时操作&#xff0c;该功能还是入库逻辑&#xff0c;此时若不进行处理&#xff0c;会造成插入表中多条重复数据&#xff0c;为此该问题需要修复。 解决办法 在接口开始进行对是否存在某个key值的判断&#xff0c;若不存在&…

【C++百宝箱】语法总结:命名空间 | 输入输出 | 缺省参数 | 函数重载

&#x1f6a9;纸上得来终觉浅&#xff0c; 绝知此事要躬行。 &#x1f31f;主页&#xff1a;June-Frost &#x1f680;专栏&#xff1a;C入门宝典 &#x1f525;本文主要探讨C的语法&#xff0c;并深入了解C如何针对C语言中存在的不合理之处进行优化改进。 目录&#xff1a; ⌛…

遭受网络攻击泄露了101GB数据

臭名昭著的BlackCat/ALPHV勒索软件团伙声称对另一个组织发起了攻击。今天轮到意大利-法国科西嘉-费里斯公司发现自己正在与勒索软件作斗争。 BlackCat 在其数据泄露网站上报告称&#xff0c;该公司是网络攻击的受害者&#xff0c;并发布了从该公司 IT 基础设施中泄露的一系列样…

Apache Airflow Celery Broker 远程命令执行 (CVE-2020-11981)漏洞复现

漏洞描述 Apache Airflow 是一个开源的分布式任务调度框架。在 1.10.10 之前的版本中&#xff0c;如果 Redis 代理&#xff08;如 Redis 或 RabbitMQ&#xff09;已被攻击者控制&#xff0c;则攻击者可以在工作进程中执行任意命令。 漏洞环境及利用 搭建docker环境 要利用此…

Rasa NLU中的组件

Rasa NLU部分主要是解决NER&#xff08;序列建模&#xff09;和意图识别&#xff08;分类建模&#xff09;这2个任务。Rasa NLP是一个基于DAG的通用框架&#xff0c;图中的顶点即组件。组件特征包括有顺序关系、可相互替换、可互斥和可同时使用。有向无环图&#xff08;DAG&…

【不正经操作】百度深度学习框架paddlepaddle本地运行python环境记录

百度深度学习框架PaddlePaddle 百度深度学习框架PaddlePaddle是一个支持深度学习和机器学习的开源框架。它由百度公司于2016年开发并发布&#xff0c;现在已经成为中国最受欢迎的深度学习框架之一&#xff0c;并且在国际上也获得了不少关注。 特点与功能 易于使用 PaddlePa…

python循环队列

导语&#xff1a; 队列是一种先进先出&#xff08;first in first out,FIFO&#xff09;的线性表&#xff0c;是一种常用的数据结构。 它只允许在表的前端&#xff08;front&#xff09;进行删除操作&#xff0c;而在表的后端&#xff08;rear&#xff09;进行插入操作&#…

盘点银行账单,订阅刺客让我们发出尖锐爆鸣

点击文末“阅读原文”即可参与节目互动 剪辑、音频 / 卷圈 运营 / SandLiu 卷圈 监制 / 姝琦 封面 / 姝琦Midjourney 产品统筹 / bobo 随着年底大家纷纷开始盘点自己的年度开销&#xff0c;我们的主播们决定为大家揭示一个常被忽视的话题 – “订阅刺客”。在这个数字化时…