敏感词过滤

敏感词过滤通常是指在文本中检测并替换或删除不适宜的内容。基于DFA(Deterministic Finite Automaton,确定性有限自动机)算法的敏感词过滤是一种高效的方法。DFA算法通过构建一个状态机来匹配敏感词,其核心思想是将每个敏感词转换成一个状态机,然后通过遍历文本来检测敏感词。

所以我们需要有一个自定义的敏感词库,并将其存储在一种高效的数据结构中。

适应快速定位查找的数据结构我们很容易想到HashMap,但我们的理想结构是类似底层HashMap(hash+树的结构)

所以我们给出的数据结构为:
private static final Map<Character, Map> DFA = new HashMap<>();
这样的设计方便我们进行拓展

代码+解释:

public class SensitiveWordFilter {
  
    private static final Map<Character, Map> DFA = new HashMap<>();

    static {
        // 初始化DFA状态机,这里以"敏感词"和"词"为例
        initDFA("敏感");
        initDFA("感词");
        initDFA("啊");
    }

    public static void initDFA(String word) {
        Map<Character, Map> currMap = DFA;//引用DFA
        for (char c : word.toCharArray()) {
            //判断这个词在不在我们构建的敏感词树中,如果不在我们需要为它创建
            /*
            * computeIfAbsent是一个Map方法,它检查当前Map是否包含指定键(这里是敏感词中的字符ch)的映射。
            * 如果不存在这样的映射,它会使用提供的函数(k -> new HashMap<>())来创建一个新的Map,并将其作为该键的值。
            * */
            currMap = (Map<Character, Map>)currMap.computeIfAbsent(c, k -> new HashMap<>());
        }
        currMap.put('\0', null); // 终止符
    }

    //过滤敏感词
    public static String filter(String str) {
        StringBuilder sb = new StringBuilder();
        int length = str.length();
        for(int i = 0; i < length; i++){
            Map<Character, Map> currMap = DFA;
            char ch = str.charAt(i);
            int currIndex = i;
            boolean found = false;//是否发现敏感词
            //当前词匹配敏感词的首字母
            while(currIndex < length && currMap.containsKey(str.charAt(currIndex))){
                //取出此敏感词作根的树
                currMap = currMap.get(str.charAt(currIndex));
                //往下匹配其余词
                currIndex++;
                if(currMap.containsKey('\0')) {//说明当前匹配到底了
                    found = true;//发现敏感词
                    //替换敏感词
                    replace(sb, i, currIndex);
                    //跳过已找出的敏感词,继续匹配
                    i = currIndex - 1;
                    break;
                }
            }
            //首字母匹配上了但是最后没匹配上
            if(!found && currIndex > i){
                currIndex = i;
            }
            //说明该词不是敏感词,首字母就没匹配上
            if(i == currIndex) {
                sb.append(ch);
            }
        }
        return sb.toString();
    }

    public static void replace(StringBuilder sb, int start, int end) {
        for(int i = start; i < end; i++) {
            sb.append("*");
        }
    }

    public static void main(String[] args) {
        String text = "敏感词的示例词。";
        String filteredText = filter(text);
        System.out.println(filteredText); // 输出: 这是一个包含***的示例***
    }
}

 虽然DFA算法在很多场景下表现良好,但它并不是唯一的解决方案,也不一定是所有情况下最高效的算法,还有AC自动机和字典树(前缀树)等算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值