[刷题] 给定字符串,对敏感词进行替换

该博客介绍了一种使用Trie树来过滤敏感词的方法,通过构建Trie树,可以高效地查找并替换字符串中的敏感词汇。博主详细展示了如何在Java中实现这一过程,包括Trie树节点的定义、添加敏感词到树中以及过滤文本的步骤。测试案例显示了方法的有效性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近看到这个问题,感觉是一个不错的题目,尝试解决并记录一下:

具体问题是: 给定一个字符串,通过指定敏感词,将字符串中敏感词进行替换。

常见有三种解法: 

  • 暴力两重For嵌套
  • KMP
  • Trie树

今天尝试用敏感词构建Trie树解决问题,代码如下:

import org.apache.commons.lang3.CharUtils;
import java.util.HashMap;
import java.util.Map;

public class trie {

    //敏感词构建的Trie树
    private class TrieNode{
        //用于标记敏感词的结尾
        private boolean isEnd = false;
        //下一层节点
        Map<Character,TrieNode> subNodes = new HashMap<>();
        //添加下一个敏感词节点
        public void addSubNode(Character c, TrieNode node){
            subNodes.put(c, node);
        }
        //获取下一个敏感词节点
        public TrieNode getSubNode(Character c){
            return subNodes.get(c);
        }
        //设置敏感词结尾
        public void setEnd(boolean end){
            this.isEnd = end;
        }
        //判断敏感词是否结尾
        public boolean getIsEnd(){
            return this.isEnd;
        }
    }

    //替换词
    private static final String DEFAULT_REPLACEMENT = "***";

    //初始化Trie树
    private TrieNode root;
    public trie(){
        root = new TrieNode();
    }

    //识别特殊符号
    private boolean isSymbol(Character c){
        int ic = (int) c;
        //非ASCII编码且不在0x2E80-0x9FFF 东亚文字范围内
        return !CharUtils.isAsciiAlphanumeric(c) && (ic < 0x2E80 || ic > 0x9FFF);
    }

    //将敏感词添加到字典树中
    public void addWord(String text){
        //trim() 函数移除字符串两侧的空白字符或其他预定义字符
        if(text == null || text.trim().equals("")){
            return;
        }
        TrieNode curNode = root;
        int length = text.length();
        for(int index = 0; index < length; ++index){
            Character c = text.charAt(index);
            //过滤敏感词中的特殊字符
            if(isSymbol(c)){
                //跳出本次循环
                continue;
            }
            TrieNode subNode = curNode.getSubNode(c);
            //添加子节点
            if(subNode == null){
                subNode = new TrieNode();
                curNode.addSubNode(c, subNode);
            }
            curNode = subNode;
            //设置敏感词标识
            if(index == length - 1){
                curNode.setEnd(true);
            }
        }
    }

    //过滤敏感词
    public String filter(String text){
        if(text == null || text.trim().equals("")){
            return text;
        }
        String replacement = DEFAULT_REPLACEMENT;
        //非线程安全
        StringBuilder result = new StringBuilder();

        TrieNode curNode = root;
        int start = 0;//确定过滤词的起点
        int end = 0;//过滤词的终点
        while(end < text.length()){
            Character c = text.charAt(end);
            //判断特殊符号
            if(isSymbol(c)){
                //进来代表是特殊符号:
                if(curNode == root){
                //没匹配到敏感词,就后移开始位置和结束位置(因为不管是否匹配到都要移动结束位置,所以写在下面),把这个符号加入结果中
                    result.append(c);
                    ++start;
                }
                //curNode不是root,代表正在匹配敏感词的过程中。略过这个符号,end后移,退出此次循环,继续下轮判断。
                ++end;
                continue;
            }
            curNode = curNode.getSubNode(c);

            //代表敏感词Trie树中不存在该字符开头的敏感词
            if(curNode == null){
                //以start开始的字符串不是敏感词
                result.append(text.charAt(start));
                //end字符串和start字符串都跳到下一个字符
                end = start + 1;
                start = end;
                //敏感词Trie树回到根节点重新等待开始
                curNode = root;
            }else if(curNode.getIsEnd()){
                //curNode.getIsEnd()=True 代表该敏感词已经遍历到尾部 需要对其进行替换
                result.append(replacement);
                end = end + 1;
                start = end;
                //敏感词Trie树回到根节点重新等待开始
                curNode = root;
            }else{
                //curNode.getIsEnd()=False 代表该敏感词已经遍历到尾部 需要对其进行替换
                ++end;
            }
        }
        //??
        result.append(text.substring(start));
        return result.toString();
    }

    //测试方法是否成功
    public static void main(String[] args){
        //构建敏感词树并添加敏感词
        trie myTrie = new trie();
        myTrie.addWord("de");
        myTrie.addWord("bca");
        myTrie.addWord("色情内容");

        //过滤文本中的敏感词
        String ans = myTrie.filter("ab cad ef");
        System.out.println(ans);
        String ans1 = myTrie.filter("以下是:色情 内容");
        String ans2 = myTrie.filter("以下是:色情·内容");
        System.out.println(ans1);
        System.out.println(ans2);

    }
}

输出内容:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值