精华内容
下载资源
问答
  • 关键词过滤

    2017-01-12 16:29:04
    关键词库创建思路:采用二叉树 zI1NTk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" _xhe_src=...

    关键词库创建思路:采用二叉树


    实现代码:

    1.关键词库初始化:

    package com.slince.test2;
    
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStreamReader;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * @Description: 初始化敏感词库,将敏感词加入到HashMap中,构建DFA算法模型
     * @Projecttest
     * @Author : chenming
     * @Date 2014420日 下午2:27:06
     * @version 1.0
     */
    public class SensitiveWordInit {
       private String ENCODING = "GBK";    //字符编码
       @SuppressWarnings("rawtypes")
       public HashMap sensitiveWordMap;
    
       public SensitiveWordInit(){
          super();
       }
    
       /**
        * @author chenming
        * @date 2014420日 下午2:28:32
        * @version 1.0
        */
       @SuppressWarnings("rawtypes")
       public Map initKeyWord(){
          try {
             //读取敏感词库
             Set<String> keyWordSet = readSensitiveWordFile();
             //将敏感词库加入到HashMap         addSensitiveWordToHashMap(keyWordSet);
             //spring获取application,然后application.setAttribute("sensitiveWordMap",sensitiveWordMap);
          } catch (Exception e) {
             e.printStackTrace();
          }
          return sensitiveWordMap;
       }
    
       /**
        * 读取敏感词库,将敏感词放入HashSet中,构建一个DFA算法模型:<br>
        * = {
        *      isEnd = 0
        *      = {<br>
        *          isEnd = 1
        *           = {isEnd = 0
        *                = {isEnd = 1}
        *                }
        *           = {
        *                isEnd = 0
        *                = {
        *                    isEnd = 1
        *                   }
        *             }
        *           }
        *      }
        *  = {
        *      isEnd = 0
        *      = {
        *         isEnd = 0
        *         = {
        *              isEnd = 0
        *              = {
        *                   isEnd = 1
        *                  }
        *              }
        *         }
        *      }
        * @author chenming
        * @date 2014420日 下午3:04:20
        * @param keyWordSet  敏感词库
        * @version 1.0
        */
       @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){        //如果存在该key,直接赋值
                   nowMap = (Map) wordMap;
                }
                else{     //不存在则,则构建一个map,同时将isEnd设置为0,因为他不是最后一个
                   newWorMap = new HashMap<String,String>();
                   newWorMap.put("isEnd", "0");     //不是最后一个
                   nowMap.put(keyChar, newWorMap);
                   nowMap = newWorMap;
                }
    
                if(i == key.length() - 1){
                   nowMap.put("isEnd", "1");    //最后一个
                }
             }
          }
       }
    
       /**
        * 读取敏感词库中的内容,将内容添加到set集合中
        * @author chenming
        * @date 2014420日 下午2:31:18
        * @return
        * @version 1.0
        * @throws Exception
        */
       @SuppressWarnings("resource")
       private Set<String> readSensitiveWordFile() throws Exception{
          Set<String> set = null;
    
          File file = new File("D:\\SensitiveWord.txt");    //读取文件
          InputStreamReader read = new InputStreamReader(new FileInputStream(file),ENCODING);
          try {
             if(file.isFile() && file.exists()){      //文件流是否存在
                set = new HashSet<String>();
                BufferedReader bufferedReader = new BufferedReader(read);
                String txt = null;
                while((txt = bufferedReader.readLine()) != null){    //读取文件,将文件内容放入到set               set.add(txt);
                }
             }
             else{         //不存在抛出异常信息
                throw new Exception("敏感词库文件不存在");
             }
          } catch (Exception e) {
             throw e;
          }finally{
             read.close();     //关闭文件流
          }
          return set;
       }
    }
    

    2.关键词检索和测试:

    package com.slince.test2;
    
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * @Description: 敏感词过滤
     * @Projecttest
     * @Author : chenming
     * @Date 2014420日 下午4:17:15
     * @version 1.0
     */
    public class SensitivewordFilter {
       @SuppressWarnings("rawtypes")
       private Map sensitiveWordMap = null;
       public static int minMatchTYpe = 1;      //最小匹配规则
       public static int maxMatchType = 2;      //最大匹配规则
    
       /**
        * 构造函数,初始化敏感词库
        */
       public SensitivewordFilter(){
          sensitiveWordMap = new SensitiveWordInit().initKeyWord();
       }
    
       /**
        * 判断文字是否包含敏感字符
        * @author chenming
        * @date 2014420日 下午4:28:30
        * @param txt  文字
        * @param matchType  匹配规则&nbsp;1:最小匹配规则,2:最大匹配规则
        * @return 若包含返回true,否则返回false
        * @version 1.0
        */
       public boolean isContaintSensitiveWord(String txt,int matchType){
          boolean flag = false;
          for(int i = 0 ; i < txt.length() ; i++){
             int matchFlag = this.CheckSensitiveWord(txt, i, matchType); //判断是否包含敏感字符
             if(matchFlag > 0){    //大于0存在,返回true
                flag = true;
             }
          }
          return flag;
       }
    
       /**
        * 获取文字中的敏感词
        * @author chenming
        * @date 2014420日 下午5:10:52
        * @param txt 文字
        * @param matchType 匹配规则&nbsp;1:最小匹配规则,2:最大匹配规则
        * @return
        * @version 1.0
        */
       public Set<String> getSensitiveWord(String txt , int matchType){
          Set<String> sensitiveWordList = new HashSet<String>();
    
          for(int i = 0 ; i < txt.length() ; i++){
             int length = CheckSensitiveWord(txt, i, matchType);    //判断是否包含敏感字符
             if(length > 0){    //存在,加入list            sensitiveWordList.add(txt.substring(i, i+length));
                i = i + length - 1;    //1的原因,是因为for会自增
             }
          }
    
          return sensitiveWordList;
       }
    
       /**
        * 替换敏感字字符
        * @author chenming
        * @date 2014420日 下午5:12:07
        * @param txt
        * @param matchType
        * @param replaceChar 替换字符,默认*
        * @version 1.0
        */
       public String replaceSensitiveWord(String txt,int matchType,String replaceChar){
          String resultTxt = txt;
          Set<String> set = getSensitiveWord(txt, matchType);     //获取所有的敏感词
          Iterator<String> iterator = set.iterator();
          String word = null;
          String replaceString = null;
          while (iterator.hasNext()) {
             word = iterator.next();
             replaceString = getReplaceChars(replaceChar, word.length());
             resultTxt = resultTxt.replaceAll(word, replaceString);
          }
    
          return resultTxt;
       }
    
       /**
        * 获取替换字符串
        * @author chenming
        * @date 2014420日 下午5:21:19
        * @param replaceChar
        * @param length
        * @return
        * @version 1.0
        */
       private String getReplaceChars(String replaceChar,int length){
          String resultReplace = replaceChar;
          for(int i = 1 ; i < length ; i++){
             resultReplace += replaceChar;
          }
    
          return resultReplace;
       }
    
       /**
        * 检查文字中是否包含敏感字符,检查规则如下:<br>
        * @author chenming
        * @date 2014420日 下午4:31:03
        * @param txt
        * @param beginIndex
        * @param matchType
        * @return,如果存在,则返回敏感词字符的长度,不存在返回0
        * @version 1.0
        */
       @SuppressWarnings({ "rawtypes"})
       public int CheckSensitiveWord(String txt,int beginIndex,int matchType){
          boolean  flag = false;    //敏感词结束标识位:用于敏感词只有1位的情况
          int matchFlag = 0;     //匹配标识数默认为0
          char word = 0;
          Map nowMap = sensitiveWordMap;
          for(int i = beginIndex; i < txt.length() ; i++){
             word = txt.charAt(i);
             nowMap = (Map) nowMap.get(word);     //获取指定key
             if(nowMap != null){     //存在,则判断是否为最后一个
                matchFlag++;     //找到相应key,匹配标识+1 
                if("1".equals(nowMap.get("isEnd"))){       //如果为最后一个匹配规则,结束循环,返回匹配标识数
                   flag = true;       //结束标志位为true   
                   if(SensitivewordFilter.minMatchTYpe == matchType){    //最小规则,直接返回,最大规则还需继续查找
                      break;
                   }
                }
             }
             else{     //不存在,直接返回
                break;
             }
          }
          if(matchFlag < 2 || !flag){        //长度必须大于等于1,为词 
             matchFlag = 0;
          }
          return matchFlag;
       }
    
       public static void main(String[] args) {
          SensitivewordFilter filter = new SensitivewordFilter();
          System.out.println("敏感词的数量:" + filter.sensitiveWordMap.size());
          String string = "老虎机,游戏机,假币,毛泽东";
          System.out.println("待检测语句字数:" + string.length());
          long beginTime = System.currentTimeMillis();
          Set<String> set = filter.getSensitiveWord(string, 1);
          long endTime = System.currentTimeMillis();
          System.out.println("语句中包含敏感词的个数为:" + set.size() + "。包含:" + set);
          System.out.println("总共消耗时间为:" + (endTime - beginTime));
       }
    }
    3.加载的关键词库的格式:简单文本格式(一行代表一个关键词)
    

    展开全文
  • 互联网关键词过滤03

    2017-01-25 14:26:57
    互联网关键词过滤
  • 互联网关键词过滤02

    2017-01-25 13:43:53
    互联网关键词过滤数据库
  • 实用网站敏感关键词过滤词库
  • PHP网站关键词过滤

    2010-06-17 15:11:54
    此程序是PHP写的关键词过滤 可以单个的进行页面的关键词防护
  • 软文关键词过滤php文件 装上服务器可以运行 没有服务器是不能运行的只提示下载的亲。。。
  • 关键词过滤–延伸多关键词过滤(业务需求) 首先最笨的方法是每个关键词完整的存放在一个容器中,文本内容解析完传过来的时候进行过滤,那么这种方法要对每一个关键词做一次完整比对,不相同则比较下一组,这种最坏的...

    关键词过滤–延伸多关键词过滤(业务需求)

    首先最笨的方法是每个关键词完整的存放在一个容器中,文本内容解析完传过来的时候进行过滤,那么这种方法要对每一个关键词做一次完整比对,不相同则比较下一组,这种最坏的情况为每匹配到一个关键词都要匹配关键词个数的次数。在文本中关键词出现频率较高时,需要检查的文件个数较多时,效率很差。

    所以我们把多关键词构建成多叉树结构(即字典树),对于每一个关键词只需要遍历查找一次
    (从根节点到终端节点为一个关键词,终端节点中成员key(用来判断是否找到关键词)保存完整的关键词)
    在这里插入图片描述

    打个比方:关键词为{计算机,软件管家,软件包,软件名称,软件},构建成上图的结构。根节点的map容器中key(map的key)为{软,计} ,每个key对应的value指向下一节点,下面两个节点的map容器中key为别为{件},{算},依次往后。

    如果要过滤的的文件中第一个字为’软’或者’计’则继续匹配,看文本中第二个字是否为’件’或者’算’,是继续匹配,每次匹配判断一下当前节点中key(成员变量key)是否为空, key不为空则说明匹配到关键词 ,下一节点不为空则继续匹配。如果不是这’软’或者’计’,则往后移动取文件的第二个字看是不是’软’或者’计’继续匹配

    业务应用:点击检查设置,选则关键词点击确定按钮后,会将关键词更新到文件中,然后将文件中的关键词加载到basic_trie类中,使用search检查返回结果(包括了关键词及其位置(相对于文本首部))

    在这里插入图片描述

    百度了一下这种应该是叫做DFA算法,基于dfa构建多叉树(字典树)

    #ifndef OTHERTRIE_HPP
    #define OTHERTRIE_HPP
    
    #include <typeinfo>
    #include <memory>
    #include <string>
    #include <map>
    #include <queue>
    
    namespace mytrie {
    
    using uchar = unsigned char;
    //存储查询到的关键词结果
    template<typename CharType>
    class result{
    public:
        std::basic_string<CharType> sentence;
        unsigned int start;
        unsigned int fin;
    public:
        explicit result(){
            start = 0;
            fin = 0;
        }
        explicit result(const std::basic_string<CharType>& sentence, unsigned int start, unsigned int fin):
            sentence(sentence), start(start), fin(fin){}
    };
    
    //构建多叉树结构的节点
    template<typename CharType>
    struct Node{
    	//只在一个关键词的最后一个节点保存完整的关键词 用于判断是否找到关键词
        std::basic_string<CharType> key;
    	//map中的key保存字节流的一个字节,value指向下一节点
        std::map<uchar, std::unique_ptr<Node<CharType>>> child;
    };
    
    template<typename CharType>
    class basic_trie{
    private:
    	//根节点
        std::unique_ptr<Node<CharType>> _root;
        bool module = typeid(uchar).hash_code() == typeid(CharType).hash_code() || typeid(char).hash_code() == typeid(CharType).hash_code();
    public:
    	//初始化根节点
        basic_trie():_root(new Node<CharType>()){}
    
    	//插入关键字 
        void insert(const std::basic_string<CharType>& key)
    	{
            Node<CharType>* root = _root.get();
            if(nullptr == root || key.empty())
    		{
                return ;
            }
    
            int len;
            if(module)
    		{
                len = key.size();
            } 
    		else 
    		{
                len = key.size() * sizeof(CharType);
            }
    		//关键词转为字节流
            uchar* p = reinterpret_cast<uchar*>(const_cast<CharType*>(key.c_str()));
            bool flag = false;
    		//一次插入形成一个分支  再次插入(调用insert)关键词形成多叉树结构
            for(auto i = 0; i < len; ++i, ++p)
    		{
                if(!root->child[*p])
    			{
                    root->child[*p] = std::unique_ptr<Node<CharType>>(new Node<CharType>());
                    flag = true;
                }
                root = root->child[*p].get();
            }
    		//一个关键词链的终端节点保存完整的关键词
            if(flag)
    		{
                root->key = key;
            }
            return ;
        }
    
    	//下一节点不为空则继续匹配 key不为空则说明匹配到关键词 
        std::vector<result<CharType>> search(const std::basic_string<CharType>& content)			    
        {
            Node<CharType>* node = _root.get();
            if(nullptr == node || content.empty())
            {
                return std::vector<result<CharType>>();
            }
    
            int len;
            if(module){
                len = content.size();
            } else {
                len = content.size() * sizeof(CharType);
            }
    
            uchar* p = reinterpret_cast<uchar*>(const_cast<CharType*>(content.c_str()));
            std::vector<result<CharType>> res;
    
            int i = 0;
            int skipNum = 0;
            while(i < len)
    		{
    			//过滤关键词中间有空格特殊字符等情况 如:"秘 密" 而不是"秘密"
                while ((i < len) && (*p <= 0x20))
    			{
                    ++i;
                    ++p;
                    ++skipNum;
                }
    
                if(node->child[*p])
    			{
    				//before the root match, skipNum reset 0
                    if(node == _root.get())
                        skipNum = 0;
                    Node<CharType>* temp = node->child[*p].get();
                    if(!temp->key.empty())
    				{
                        res.emplace_back(result<CharType>(temp->key, i + 1 - skipNum - temp->key.size() * sizeof(CharType), i));
                    }
                    node = node->child[*p].get();
    			}
    			else
    			{
                    skipNum = 0;
                    node = _root.get();
                }
                ++p;
                ++i;
            }
            return res;
        }
    };
    
    }
    
    #endif // OTHERTRIE_HPP
    
    展开全文
  • 关键词过滤包,可以返回被过滤词,采用正则表达是的方式来实现的,效率还可以!
  • Vb编写的网站关键词过滤器简易版,限制某些单词在网页上显示,有意思吧!
  • 1. DFA实现的关键词过滤,性能不再受限于关键词的数量,只与被检索的文本长度有关。时间复杂度为小于等于O(n),n是被检索文本的长度。 2. DFA关键词过滤,是精准过滤,无法实现模糊过滤,如我是*人,*匹配单个字符,...

    一、前言

    有一个关键词库,此时需要检索一段文本中是否出现词库中的关键词,该如何实现?

    小白回答:将所有的关键词放入一个set集合,然后遍历集合一个个匹配那段文本,存在的关键词放入另一个集合。实现代码如下:

    public class Test131 {
        public static void main(String[] args) {
            Set<String> wordSet = new HashSet<String>();
            wordSet.add("产品经理");
            wordSet.add("产品总监");
            wordSet.add("程序员");
            String content= "产品经理工作内容包含需求收集,需求分析,需求落地,项目跟踪,项目上线,数据跟踪以及对业务人员进行培训,协助运营、销售、客服等开展工作。";
            Set<String> haveWordSet = new HashSet<String>();
            for (String word : wordSet) {
                if (content.contains(word)) {
                    haveWordSet.add(word);
                }
            }
            System.out.println(haveWordSet);
        }
    }
    // [产品经理]
    

    思路很简单,也很容易理解,但是当关键词有几千、几万个时,性能会急剧下降。分析一下时间复杂度,遍历关键词是O(n),从文字段落检索的时间复杂度也是O(n),合起来就是O(n^2)。

    有没有其他更优的解决方案呢?有!就是DFA算法!

    二、何为DFA算法

    DFA即Deterministic Finite Automaton,翻译过来就是确定性有限自动机。简单原理就是:在一个有限的集合,其中的元素都有两种状态,结束和继续(可以用0代表继续,1代表结束),可以从一个元素检索到下一个元素,直到元素的状态为结束为止。

    dfa

    三、DFA算法优化关键词过滤

    套用DFA算法的原理,例如有一些关键词:产品经理、产品总监、程序员,构建DFA算法容器如下:

    java-dfa

    看着像一棵棵树,现在判断一个词是否在词库中,比如测试员,检索是否有”测“字开头的“树”,很快就能判断没有测试员这个词,比如检索“产品经理”,则可以找到”产“字开头的“树”,直接排除了“程序员”那棵“树”,这就大大缩小了范围。

    算一下时间复杂度,从词库中匹配关键词,时间复杂度是O(1),遍历文字段落依然和文字的个数有关,时间复杂度最差(如果文本没有一个关键词)为O(n),合起来就是小于等于O(n)。使用DFA实现关键词过滤的优化点在于:检索的时间复杂度不会因为关键词数量的增加而受影响,只与被检索的文字长度有关。

    四、java代码实现

    分析数据结构,每一个字符都要存一个状态,可以用map实现,如果状态未结束还要存下一个字符的指针,也可以用map实现,这样就是map套map。如下:一个大map里有两个key,程和产,value值又是map套map。

    {={isEnd=0,={isEnd=0,={isEnd=1}
           }
        },={isEnd=0,={isEnd=0,={isEnd=0,={isEnd=1}
              },={isEnd=0,={isEnd=1}
              }
           }
        } 
    }
    

    完整代码示例:

    public class Test131 {
        public static void main(String[] args) {
            String content= "产品经理工作内容包含需求收集,需求分析,需求落地,项目跟踪,项目上线,数据跟踪以及对业务人员进行培训,协助运营、销售、客服等开展工作。";
            Set<String> wordSet = new HashSet<String>();
            wordSet.add("产品经理");
            wordSet.add("产品总监");
            wordSet.add("程序员");
            init(wordSet);
            System.out.println("wordMap=" + m_kwWordMap);
            Set<String> haveWords = getWord(content, MIN_MATCH_TYPE);
            System.out.println("haveWords=" + haveWords);
    
        }
    
        /**
         * 初始化DFA关键词容器
         * @param words
         */
        @SuppressWarnings({ "rawtypes", "unchecked" })
        public static void init(Set<String> words) {
            // 预先 设置初始容量,以免扩容影响性能。
            Map wordMap = new HashMap(words.size());
            for (String word : words) {
                Map nowMap = wordMap;
                for (int i = 0; i < word.length(); i++) {
                    // 转换成char型
                    char keyChar = word.charAt(i);
                    // 判断是否已经有一个map树,只有在一个词的首字符有用
                    Object tempMap = nowMap.get(keyChar);
                    if (tempMap != null) {
                        // 存在,则共享一个map树根
                        nowMap = (Map) tempMap;
                    }
                    // 不存在则构建一个map树,
                    else {
                        // 设置状态位
                        Map<String, String> newMap = new HashMap<String, String>();
                        // 判断是设置 0还是1
                        newMap.put("isEnd", i == word.length() - 1 ? "1" : "0");
                        // 给keyChar该字符设置状态位
                        nowMap.put(keyChar, newMap);
                        // 将状态位map赋值给nowMap,表示下一个字符的指针和状态位在同一个map里。
                        nowMap = newMap;
                    }
                }
            }
            // 上面始终修改的是nowMap,最后形成的是wordMap,原因是,预先wordMap赋值给了nowMap,
            // 使得wordMap和nowMap中的map地址值共享,更新了nowMap中的map就是更新了wordMap。
            m_kwWordMap = wordMap;
        }
    
        /**
         * 检索关键词
         * @param txt 被检索的文本
         * @param beginIndex  被检索文本的开始位置
         * @param matchType 匹配类型
         * @return 返回检索到的关键词长度,用于从文本中截取
         */
        public static int checkWord(String txt, int beginIndex, int matchType) {
            // 匹配标识数默认为0
            Map nowMap = m_kwWordMap;
            int matchFlag = 0;
            int matchMaxFlag = 0;
            for (int i = beginIndex; i < txt.length(); i++) {
                char word = txt.charAt(i);
                // 获取指定key
                nowMap = (Map) nowMap.get(word);
                // 存在,则判断是否为最后一个
                if (nowMap != null) {
                    // 找到相应key,匹配标识+1
                    matchFlag++;
                    // 如果为最后一个匹配规则,结束循环,返回匹配标识数
                    if ("1".equals(nowMap.get("isEnd"))) {
                        // 将matchFlag赋值给matchMaxFlag,为的是,
                        // 后面要是继续按最大匹配原则匹配时,匹配不到则按最小匹配原则的结果为准。
                        matchMaxFlag = matchFlag;
                        // 最小规则,直接返回,最大规则还需继续查找
                        if (MIN_MATCH_TYPE == matchType) {
                            break;
                        }
                    }
                }
                // 不存在,直接返回
                else {
                    break;
                }
            }
            return matchMaxFlag;
        }
    
        /**
         * 从文本中检索出关键词
         * @param txt 被检索的文本
         * @param matchType 匹配类型
         * @return
         */
        public static Set<String> getWord(String txt, int matchType) {
            Set<String> set = new HashSet<String>();
            for (int i = 0; i < txt.length(); i++) {
                // 判断是否包含关键词,length > 0 有,且是关键词长度
                int length = checkWord(txt, i, matchType);
                // 存在,加入set中
                if (length > 0) {
                    // 从原文中截取 并放入set
                    set.add(txt.substring(i, i + length));
                    // 减1的原因,因为for会自增
                    i = i + length - 1;
                }
            }
            return set;
        }
    
        private static Map m_kwWordMap = null;
        // 最小匹配原则,如果关键词中有中国和中国人,文本内容为“我是中国人”,最小匹配原则匹配出中国
        public static final int MIN_MATCH_TYPE = 1;
        // 最大匹配原则,如果关键词中有中国和中国人,文本内容为“我是中国人”,最大匹配原则匹配出中国人
        public static final int MAX_MATCH_TYPE = 2;
    }
    
    // wordMap={程={isEnd=0, 序={员={isEnd=1}, isEnd=0}}, 产={品={总={监={isEnd=1},      isEnd=0}, isEnd=0, 经={理={isEnd=1}, isEnd=0}}, isEnd=0}}
    // haveWords=[产品经理]
    

    五、总结

    1. DFA算法利用map套map的原理,极大程度上优化了检索性能,时间复杂度为小于等于O(n),n是被检索文本的长度。
    2. DFA实现的关键词过滤,性能不再受限于关键词的数量,只与被检索的文本长度有关。
    3. DFA关键词过滤,是精准过滤,无法实现模糊过滤,如我是*人*匹配单个字符,%匹配多个字符。

    参考:https://www.cnblogs.com/twoheads/p/11349541.html 需要注意该文章中checkWord函数最大匹配原则时是有bug的,本人的示例已加matchMaxFlag更正。

    PS: 如若文章中有错误理解,欢迎批评指正,同时非常期待你的评论、点赞和收藏。我是徐同学,愿与你共同进步!

    展开全文
  • 一个简单的关键词过滤工具,在原来的基础上做了修改,兼容增补字符并做了英文单词的简单处理 原型参考1:http://cmsblogs.com/?p=1031; 原型参考2:https://blog.csdn.net/chenssy/article/details/26961957 ...

    一个简单的关键词过滤工具,在原来的基础上做了修改,兼容增补字符并做了英文单词的简单处理

    原型参考1:http://cmsblogs.com/?p=1031

    原型参考2:https://blog.csdn.net/chenssy/article/details/26961957

     

    
    import java.util.*;
    import java.util.concurrent.ConcurrentHashMap;
    
    /**
     *
     */
    public class Demo {
    
        /**
         * 词尾标记
         */
        private static final int TAILED = 0;
    
        /**
         * 关键词集合
         */
        public static volatile ConcurrentHashMap<Integer, Object> wordMap = new ConcurrentHashMap<>();
    
        /**
         * @param words
         */
        public static synchronized void init(Set<String> words) {
            put(words, wordMap);
        }
    
        private static synchronized void put(Set<String> words, ConcurrentHashMap<Integer, Object> map) {
            ConcurrentHashMap<Integer, Object> curMap;
            for (String word : words) {
                curMap = map;
                int[] codePoints = word.toLowerCase().codePoints().toArray();
    
                for (int i = 0; i < codePoints.length; i++) {
                    int codePoint = codePoints[i];
                    ConcurrentHashMap<Integer, Object> segment = (ConcurrentHashMap<Integer, Object>) curMap.get(codePoint);
                    if (segment == null) {
                        segment = new ConcurrentHashMap<>();
                        segment.put(TAILED, false);
                        curMap.put(codePoint, segment);
                    }
                    curMap = segment;
    
                    //词尾
                    if (i == codePoints.length - 1) {
                        segment.put(TAILED, true);
                    }
                }
            }
        }
    
        /**
         * 关键词过滤
         *
         * @param txt 文字
         * @return
         */
        public static void analyse(String txt) {
            Map<String, Integer> result = new HashMap<>();
            int[] codePoints = txt.toLowerCase().codePoints().toArray();
            int[] processed = txt.codePoints().toArray();
    
            for (int i = 0; i < codePoints.length; i++) {
                int length = checkWord(codePoints, i);
                if (length > 0) {
                    String candidate = new String(codePoints, i, length);
                    //简单处理单词
                    if (candidate.matches("[a-zA-Z]+")) {
                        if (i > 0) {
                            int beforeOne = codePoints[i - 1];
                            if ((beforeOne >= 'A' && beforeOne <= 'Z') || (beforeOne >= 'a' && beforeOne <= 'z')) {
                                i = i + length - 1;
                                continue;
                            }
                        }
                        if (codePoints.length > i + length) {
                            int afterOne = codePoints[i + length];
                            if ((afterOne >= 'A' && afterOne <= 'Z') || (afterOne >= 'a' && afterOne <= 'z')) {
                                i = i + length - 1;
                                continue;
                            }
                        }
                    }
    
                    Arrays.fill(processed, i, i + length, '*');
                    result.compute(candidate.toLowerCase(), (k, v) -> null == v ? 1 : ++v);
                    i = i + length - 1;
                }
            }
    
            System.out.println("源文本:" + txt);
            System.out.println("替换后文本:" + new String(processed, 0, processed.length));
            System.out.println("匹配结果:" + result);
        }
    
    
        /**
         * @param codePoints
         * @param beginIndex
         * @return 
         */
        private static int checkWord(int[] codePoints, int beginIndex) {
            int matchedLength = 0, validLength = 0;
            Map<Integer, Object> curMap = wordMap;
    
            for (int i = beginIndex; i < codePoints.length; i++) {
                int codePoint = codePoints[i];
                curMap = (Map<Integer, Object>) curMap.get(codePoint);
                if (curMap != null) {
                    matchedLength++;
                    if (Objects.equals(true, curMap.get(TAILED))) {
                        validLength = matchedLength;
                    }
                    //尽可能匹配
                    continue;
                }
                break;
            }
    
            return validLength;
        }
    
        public static void main(String[] args) {
            Demo.init(new HashSet<>(Arrays.asList("aa", "bb", "哈", "哈哈")));
            Demo.analyse("AB 😄 aa a Bb ab1Bb 哈哈bbb");
        }
    
    }
    

     运行结果:

    展开全文
  • 简单的关键词过滤器有两个功能:一个是多关键词组合功能并去掉重复项;一个是查找遗漏的关键词。 用途:SEO 开发语言:c++ 源代码见我的博客911.cnblogs.com
  • 关键词过滤

    2010-03-27 17:25:00
    关键词过滤器有两个功能:一个是多关键词组合功能并去掉重复项;一个是查找遗漏的关键词核心代码:组合功能://组合UpdateData(TRUE);CStringspace=_T("");//间隔CStringfirstKeyword=_T("");CStringresualt=_T("");...
  • 基于向量空间模型的垃圾邮件关键词过滤研究,邬正伟,,现今电子邮件已成为信息交互的重要工具,可惜垃圾邮件(spam)的泛滥,造成大量的网络资源浪费,反动邮件甚至严重破坏了社会稳定��
  • 基于WM多模式匹配的关键词过滤引擎是采用ACE框架,C++语言实现的能处理大并发量过滤系统。编译时得需要ACE库,希望各位能用得上吧。
  • iis关键词过滤系统!免费版本没有功能限制,站长实用工具。
  • 搜索后有搜索历史记录,自动提示,提示内容为历史记录对比搜索关键词过滤,可以设置是包含过滤还是守字母组过滤,可以设置提示内容最大显示数,这些自定义设置代码里有,被注释了,根据需要自己调整代码吧
  • 在做关键词过滤的时候,搜索到yeerh
  • 关键词过滤扩展,用于检查一段文本中是否出现敏感词,基于Double-Array Trie 树实现 一、安装libiconv 这个是libdatrie的依赖项 PHP7.2的用法: wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz ...
  • php 关键词过滤

    2019-11-28 15:21:25
    $badword = array( '张三','张三丰','张三丰田' ); $badword1 = array_combine( $badword, array_fill(0, count($badword), '*') ); $bb = '我今天开着张三丰田上班'; $str = strtr($bb, $badword1);...
  • 摘要:基于多叉树查找的Java敏感词过滤、java关键词过滤工具包原理 本算法对纯文本匹配执行效率:5000字35毫秒
  • java敏感词关键词过滤

    千次阅读 2018-07-05 08:54:44
    * 敏感词过滤器,以过滤速度优化为主。 * * 增加一个敏感词:{@link #put(String)} * * 过滤一个句子:{@link #filter(String, char)} * * 获取默认的单例:{@link #DEFAULT} */ public class...
  • dedeCMS系统模板安装完毕之后,如何进行非法词汇的屏蔽,以及关键词过滤替换呢? 一、所需修改文件路径: C:\wamp64\www\install\config.cache.inc.php 二、对应设置词汇,进行信息筛选、屏蔽、过滤: 在第21行:...
  • php 敏感关键词过滤

    2018-05-22 16:21:24
    $hei=array( '中国', '日本' ); $blacklist="/".implode("|",$hei)."/i"; $str="中国一是一个很好的国家"... if(preg_match($blacklist, $str, $matches)){ print &...
  • 网站、论坛、游戏等等过滤关键词。 2000千个,本人辛苦收集的。提供下载
  • 我在使用awk根据关键词查询文本内容时,如果要过滤关键词中包含空格,内容就无法查询出来。 例如我的文本中有如下一句话: ``` 2020-07-24 18:31:47.141996 [INFO] mrcp_client_connection.c:459 (ASR-...
  • 对文本内容进行关键词过滤

    千次阅读 2017-12-05 21:17:58
    网络中的信息有一些是有害的,因此我们经常需要对网络信息进行屏蔽或过滤过滤信息一般有禁止输入、信息替换(如用“*”替换)、直接删除等方式。这些信息过滤业务的处理一般在后台完成,如果... 对文本内容进行关键词
  • C#实现文本关键词过滤

    千次阅读 2016-08-08 14:13:01
    思路来自编译原理,当然跟编译原理的算法... /// 关键词标识方法 /// /// 待处理文本 /// 关键词,字符串,用符号separator隔开,可以改为直接传进来数组 /// 关键词加的buff 前 /// 关键词加的buff 后 /// 分
  • C# 非法关键词过滤 ToolGood.Words插件

    千次阅读 2019-08-20 11:58:04
    //可以从数据库或者txt文本中读取非法关键词(缓存什么也可以加上) string content = @"xx的TA做着白日梦,正是盛夏时节,不比初春时的一片新绿,知道好日子才开始,所以明亮快活,眼前的绿是沉甸甸的,或许是因为...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 54,799
精华内容 21,919
关键字:

关键词过滤