java实现敏感词过滤

java过滤敏感词

参考文章 http://blog.youkuaiyun.com/chenssy/article/details/26961957

想通过博客把自己在平常工作中用到的东西和感悟记录下来,分享给更多的人。这是我写的第一篇博客,主要是关于java敏感词过滤的。最近做了个基于ssm框架的app服务端的敏感词过滤的功能。一般来说文字过滤第一种想到的是简单的把敏感词放到集合中,获取页面上传文字,然后进行匹配。或者是用正则表达式等进行匹配。但是这样的只能进行简单的效率较低的检索。通过网上查阅资料发现可以使用DFA算法。

DFA简介

在实现文字过滤的算法中,DFA是唯一比较好的实现算法。DFA即Deterministic Finite Automaton,也就是确定有穷自动机,它是是通过event和当前的state得到下一个state,即event+state=nextstate。下图展示了其状态的转换
这里写图片描述

在这幅图中大写字母(S、U、V、Q)都是状态,小写字母a、b为动作。通过上图我们可以看到如下关系
a b b
S —–> U S —–> V U —–> V
在实现敏感词过滤的算法中,我们必须要减少运算,而DFA在DFA算法中几乎没有什么计算,有的只是状态的转换。

Java实现DFA算法

在Java中实现敏感词过滤的关键就是DFA算法的实现。首先我们对上图进行剖析。在这过程中我们认为下面这种结构会更加清晰明了。
这里写图片描述
同时这里没有状态转换,没有动作,有的只是Query(查找)。我们可以认为,通过S query U、V,通过U query V、P,通过V query U P。通过这样的转变我们可以将状态的转换转变为使用Java集合的查找。诚然,加入在我们的敏感词库中存在如下几个敏感词:日本人、日本鬼子、毛.泽.东。那么我需要构建成一个什么样的结构呢?首先:query 日 —> {本}、query 本 —>{人、鬼子}、query 人 —>{null}、query 鬼 —> {子}。形如下结构:
这里写图片描述
下面我们在对这图进行扩展:
这里写图片描述

这样我们就将我们的敏感词库构建成了一个类似与一颗一颗的树,这样我们判断一个词是否为敏感词时就大大减少了检索的匹配范围。比如我们要判断日本人,根据第一个字我们就可以确认需要检索的是那棵树,然后再在这棵树中进行检索。但是如何来判断一个敏感词已经结束了呢?利用标识位来判断。所以对于这个关键是如何来构建一棵棵这样的敏感词树。下面我已Java中的HashMap为例来实现DFA算法。具体过程如下:
日本人,日本鬼子为例
1、在hashMap中查询“日”看其是否在hashMap中存在,如果不存在,则证明已“日”开头的敏感词还不存在,则我们直接构建这样的一棵树。跳至3。
2、如果在hashMap中查找到了,表明存在以“日”开头的敏感词,设置hashMap = hashMap.get(“日”),跳至1,依次匹配“本”、“人”。
3、判断该字是否为该词中的最后一个字。若是表示敏感词结束,设置标志位isEnd = 1,否则设置标志位isEnd = 0;
这里写图片描述
程序实现如下:


    /** 
         * 读取敏感词库,将敏感词放入HashSet中,构建一个DFA算法模型:<br> 
         * 中 = { 
         *      isEnd = 0 
         *      国 = {<br> 
         *           isEnd = 1 
         *           人 = {isEnd = 0 
         *                民 = {isEnd = 1} 
         *                } 
         *           男  = { 
         *                  isEnd = 0 
         *                   人 = { 
         *                        isEnd = 1 
         *                       } 
         *               } 
         *           } 
         *      } 
         *  五 = { 
         *      isEnd = 0 
         *      星 = { 
         *          isEnd = 0 
         *          红 = { 
         *              isEnd = 0 
         *              旗 = { 
         *                   isEnd = 1 
         *                  } 
         *              } 
         *          } 
         *      }         

         * @param keyWordSet  敏感词库        
         */  
        @SuppressWarnings({ "rawtypes", "unchecked" })  
        private void addSensitiveWordToHashMap(Set<String> keyWordSet) {  
            sensitiveWordMap = new HashMap(keyWordSet.size());     //初始化敏感词容器,减少扩容操作  
            String key = null;    
            Map nowMap = null;  
            Map<String, String> newWorMap = null;  
            //迭代keyWordSet  
            Iterator<String> iterator = keyWordSet.iterator();  
            while(iterator.hasNext()){  
                key = iterator.next();    //关键字  
                nowMap = sensitiveWordMap;  
                for(int i = 0 ; i < key.length() ; i++){  
                    char keyChar = key.charAt(i);       //转换成char型  
                    Object wordMap = nowMap.get(keyChar);       //获取  

                    if(wordMap != null){        
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值