DFA算法实现敏感词过滤

    写项目时,得到一个新的需求,即实现敏感词的过滤,上网查了下,有几种实现方法,采取了DFA算法,即确定的有穷自动机算法,当初学习编译原理的时候为啥没想到DFA还能这么做,看来眼界和意识还是不够,得锻炼。

    所谓的确定有限自动机算法,其实本质上是自上而下的文法分析中的一个步骤,即建立起一颗从上到下的语法树。

    比如有如下敏感词:

大傻瓜,大傻瓜瓜逼,大傻子

    建立起的语法树则是:
在这里插入图片描述
    针对该情况,可以用HashMap来存贮语法树,当然,不同的敏感词开头则需要不同的语法树,下面列出敏感词转语法树的代码:

/**
     * 将敏感关键词建立起多颗索引树,以HashMap存贮
     * @param keyWordSet
     * @return
     */
    public void addKeyWordtoHashMap(Set<String> keyWordSet){
        keyWordMap=new HashMap<String,String>();
        String key = null;
        Map nowMap = null;
        Map<String, String> newWorMap = null;
        Iterator<String> iterator = keyWordSet.iterator();
        while(iterator.hasNext()) {
            key = iterator.next();
            nowMap = keyWordMap;
            for (int i = 0; i < key.length(); i++) {
                char keyChar = key.charAt(i);
                Object wordMap = nowMap.get(keyChar);
                if (wordMap != null) {
                    nowMap = (Map) wordMap;
                } else {
                    newWorMap = new HashMap<String, String>();
                    //End为结束标志,1表示为该分支已完成,0表示该分支还未完成
                    newWorMap.put("End", "0");
                    nowMap.put(keyChar, newWorMap);
                    nowMap = newWorMap;
                }
                if (i == key.length() - 1) {
                    nowMap.put("End", "1");
                }
            }
        }
    }

    敏感词可以存贮在数据库中,从中取出出来,存入集合中来建立起语法树,例如有以下敏感词:

[大傻逼, 傻子, 傻逼, 大傻子]

    利用上述的代码建立起的HashMap有:

{={End=0,={={End=1}, End=0,={End=1}}},={={End=1}, End=0,={End=1}}}

    接下来就是检测文本中是否含有敏感词了,检测敏感词的代码如下:

/**
     * 检查从开始出的敏感词检测
     * @param beginIndex
     * @param text
     * @return
     */
    private int checkSensitiveWord(int beginIndex,String text){
        Map newWordMap=keyWordMap;
        int indexCount=0;//记录扫描敏感词而产生的偏移量
        boolean isContainSensitiveWord=false;//用来记录是否检测到敏感词
        char temp=0;
        for (int i=beginIndex;i<text.length();i++){
            temp=text.charAt(i);
            //忽略无效字符
            if (ignoreWord.get(temp)!=null){
                indexCount++;
                continue;
            }
            newWordMap=(Map)newWordMap.get(temp);
            if (newWordMap!=null){
                indexCount++;
                if ("1".equals(newWordMap.get("End"))){
                    isContainSensitiveWord=true;
                }
            }else {
                break;
            }
        }
        //敏感词长度不能小于2
        if (indexCount<2 || !isContainSensitiveWord){
            indexCount=0;
        }
        //System.out.println(indexCount+"jjjj");
        return indexCount;
    }

    ignoreWord同样是一个HashMap,里面存贮着无效的字符,比如:

public static char[] IgnoreWords={'`','~','!','@','#','$','%','^','&','*','(',')',' ','.','。','·'};

    获取文本中的敏感词以及替换:

 /**
     * 获得文中的敏感词汇
     * @param text
     * @return
     */
    public Set<String> getSensitiveWord(String text){
        Set<String> sensitiveWordList = new HashSet<String>();
        for(int i = 0 ; i < text.length() ; i++){
            int length = checkSensitiveWord(i,text);
            if(length > 0){
                //将敏感词给截取下来,存入集合中
                sensitiveWordList.add(text.substring(i, i+length));
                //text.substring(i,i+length);
                i = i + length - 1;
            }
        }
        return sensitiveWordList;
    }

    /**
     * 指定字符串替换掉敏感词汇
     * @param text
     * @param replaceChar
     * @return
     */
    public String replaceSensitiveWord(String text,String replaceChar) throws IOException {
        init();
        String resultTxt = text;
        Set<String> set = getSensitiveWord(text);
        Iterator<String> iterator = set.iterator();
        String word = null;
        String replaceString = null;
        while (iterator.hasNext()) {
            word = iterator.next();
            int index=resultTxt.indexOf(word);
resultTxt=resultTxt.substring(0,index)+replaceChar+resultTxt.substring(index+word.length());
        }
        return resultTxt;
    }

    从上述的代码可以看出DFA算法的时间复杂度是O(n2),加入有如下需验证的文本:

傻**逼**啦啦&&啦#傻子#啦啦啦大@  傻#子

    运行得出的结果为:

语句中包含的敏感词汇:3。包含[#傻子#, 大@  傻#子, 傻**逼**]
[一两清风,半盏明月]啦啦&&啦[一两清风,半盏明月]啦啦啦[一两清风,半盏明月]
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值