java Map实现敏感词过滤 DFA算法

首先,DFA算法是啥

我的理解是,我们现在所接触的网络空间,难免鱼龙混杂,一些特殊意义,或满是芬芳气息的词汇在大多数地方都会屏蔽掉,或者用无意义的符号替换。
举个例子就是王者荣耀聊天系统,你如果打字出现芬芳气息的词汇,就会给你的词汇替换成*,今天要实现的就是这样的功能。

一、你可以自己去网上找找敏感词的词库

把它拿来作为测试的对象。当然了下面我也提供链接,需要的请自行下载。敏感词库

二、接下来是如何将词库里面的每个词汇都转为一棵大树的一部分

java mongdb 过滤_敏感词过滤


类似这样的一颗树,怎么建呢?

1、一个外层循环所有的敏感词,循环每个敏感词的每一个字符看Map中有没有,注意这里的Map是我的根目录
2、有的话就循环判断,进一层的字符在temp中是否存在,这里的temp是一个当前目录的指针
3、有的话就继续判断,没有的话就把当前的Map加入没有的字符
4、一定要注意的是有一个temp是指向当前目录的指针,指针要考虑什么时候是需要回来的

转换代码如下

public static Map<Character,Map> totran(List<String> wo,Map<Character, Map> maps, Map<Character, Map> temstap){
        for (int i = 0; i < wo.size(); i++) {
        //一定要注意指针要回来
            temstap = maps;
            char[] chars = wo.get(i).toCharArray();
            for (int j = 0; j < chars.length; j++) {
                if (temstap.containsKey(chars[j])) {
                    temstap = temstap.get(chars[j]);
                } else {
                    Map<Character, Map> news = new HashMap<>();
                    temstap.put(chars[j], news);
                    temstap = news;
                    //一定要注意指针要回来
                }
            }
            temstap.put('\t', null);
        }
        return maps;
    }

三、将文章中的敏感词替换

有了上面的铺垫,下面的也就水到渠成

/**
     * 将文章与敏感词Map结构进行匹配,将敏感词替换为‘*’
     *
     * @param str
     * @param maps
     * @param temstap
     */
    public static char[] tranfro(String str, Map<Character, Map> maps, Map<Character, Map> temstap) {
        temstap = maps;
        int c = 0;
        //c 和 j 都是我用的标志位,同样要注意什么时候要回来
        int j = 1;
        char[] charss = str.toCharArray();
        for (int i = 0; i < str.length(); i++) {
            if (temstap.containsKey(charss[i])) {
                temstap = temstap.get(charss[i]);
                c = c + 1;
                if (temstap.containsKey('\t')) {
                    while (i - c + j != i + 1) {
                        charss[i - c + j] = '*';
                        j++;
                    }
                    c = 0;
                    j = 1;
                     //c 和 j 都是我用的标志位,同样要注意什么时候要回来
                    temstap = maps;
                }
            } else {
                i = i - c;
                c = 0;
                 //c 和 j 都是我用的标志位,同样要注意什么时候要回来
                //标志位变动的时候,考虑全所有指针要不要变
                temstap = maps;
            }
        }
        return charss;
    }

全部源代码:

package com.example.demo.newyears;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author:Yun
 * @Date:2022/01/06/13:44
 * @Description:
 **/
public class TestMap {
    private static final String url = "jdbc:mysql://121.196.23.247:33306/library?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";
    private static final String userName = "root";
    private static final String passwd = "!QAZ@WSX3edc";

    static {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {

        try (
                Connection conn = DriverManager.getConnection(url, userName, passwd);
                PreparedStatement ps = conn.prepareStatement("select name from sensitive_words ;")) {
            ResultSet rs = ps.executeQuery();

            //用List来存放敏感词
            List<String> wo = new ArrayList<>();
            while (rs.next()) {
                wo.add(rs.getString("name"));
            }

            Map<Character, Map> maps = new HashMap<>();    //根目录
//        Map<Character, Map> temstap ; //临时

            Map<Character, Map> temstap = new HashMap<>();
            System.out.println(totran(wo, maps, temstap));
            rs.close();

            //将文章与敏感词Map结构进行匹配,将敏感词替换为‘*’
            String str = "结婚证中国二等奖让";
            Map<Character, Map> tem = new HashMap<>();
            System.out.println(tranfro(str, maps, tem));
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }


    public static Map<Character, Map> totran(List<String> wo, Map<Character, Map> maps, Map<Character, Map> temstap) {
        for (int i = 0; i < wo.size(); i++) {
            temstap = maps;
            char[] chars = wo.get(i).toCharArray();
            for (int j = 0; j < chars.length; j++) {
                if (temstap.containsKey(chars[j])) {
                    temstap = temstap.get(chars[j]);
                } else {
                    Map<Character, Map> news = new HashMap<>();
                    temstap.put(chars[j], news);
                    temstap = news;
                }
            }
            temstap.put('\t', null);
        }
        return maps;
    }

    /**
     * 将文章与敏感词Map结构进行匹配,将敏感词替换为‘*’
     *
     * @param str
     * @param maps
     * @param temstap
     */
    public static char[] tranfro(String str, Map<Character, Map> maps, Map<Character, Map> temstap) {
        temstap = maps;
        int c = 0;
        int j = 1;
        char[] charss = str.toCharArray();
        for (int i = 0; i < str.length(); i++) {
            if (temstap.containsKey(charss[i])) {
                temstap = temstap.get(charss[i]);
                c = c + 1;
                if (temstap.containsKey('\t')) {
                    while (i - c + j != i + 1) {
                        charss[i - c + j] = '*';
                        j++;
                    }
                    c = 0;
                    j = 1;
                    temstap = maps;
                }
            } else {
                i = i - c;
                c = 0;
                //标志位变动的时候,考虑全所有指针要不要变
                temstap = maps;
            }
        }
        return charss;
    }
}

这里想和大家分享一个很有价值的东西

打断点,dubug看自己的循环哪里有问题,出现了意料外的情况,大多数都是自己循环的条件没写对,或漏了条件没写回归。

java mongdb 过滤_树结构_02

点这里你可以直接去,出现bug的那一层,看当前的参数哪里出现了问题

java mongdb 过滤_DFA算法_03

最后如有疑问请留言