最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java實現(xiàn)DFA算法對敏感詞、廣告詞過濾功能示例

 更新時間:2017年11月24日 11:02:18   作者:Andyzty  
本篇文章主要介紹了Java實現(xiàn)DFA算法對敏感詞、廣告詞過濾功能示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下

一、前言

開發(fā)中經(jīng)常要處理用戶一些文字的提交,所以涉及到了敏感詞過濾的功能,參考資料中DFA有窮狀態(tài)機(jī)算法的實現(xiàn),創(chuàng)建有向圖。完成了對敏感詞、廣告詞的過濾,而且效率較好,所以分享一下。

具體實現(xiàn):

 1、匹配大小寫過濾
 2、匹配全角半角過濾
 3、匹配過濾停頓詞過濾。
 4、敏感詞重復(fù)詞過濾。

例如:

支持如下類型類型過濾檢測:

fuck 全小寫

FuCk 大小寫

fuck全角半角

f!!!u&c ###k 停頓詞

fffuuuucccckkk 重復(fù)詞

敏感詞過濾的做法有很多,我簡單描述我現(xiàn)在理解的幾種:

①查詢數(shù)據(jù)庫當(dāng)中的敏感詞,循環(huán)每一個敏感詞,然后去輸入的文本中從頭到尾搜索一遍,看是否存在此敏感詞,有則做相

應(yīng)的處理,這種方式講白了就是找到一個處理一個。

優(yōu)點:so easy。用java代碼實現(xiàn)基本沒什么難度。

缺點:這效率讓我心中奔過十萬匹草泥馬,而且匹配的是不是有些蛋疼,如果是英文時你會發(fā)現(xiàn)一個很無語的事情,比如英文

a是敏感詞,那我如果是一篇英文文檔,那程序它妹的得處理多少次敏感詞?誰能告訴我?

②傳說中的DFA算法(有窮自動機(jī)),也正是我要給大家分享的,畢竟感覺比較通用,算法的原理希望大家能夠自己去網(wǎng)上查查

資料,這里就不詳細(xì)說明了。

優(yōu)點:至少比上面那sb效率高點。

缺點:對于學(xué)過算法的應(yīng)該不難,對于沒學(xué)過算法的用起來也不難,就是理解起來有點gg疼,匹配效率也不高,比較耗費內(nèi)存,

敏感詞越多,內(nèi)存占用的就越大。

③第三種在這里要特別說明一下,那就是你自己去寫一個算法吧,或者在現(xiàn)有的算法的基礎(chǔ)上去優(yōu)化,這也是小Alan追求的至

高境界之一,如果哪位淫兄有自己的想法一定別忘了小Alan,可以加小Alan的QQ:810104041教小Alan兩招耍耍。

二、代碼實現(xiàn)

其目錄結(jié)構(gòu)如下:

其中resources資源目錄中:

stopwd.txt :停頓詞,匹配時間直接過濾。

wd.txt:敏感詞庫。

1、WordFilter敏感詞過濾類

package org.andy.sensitivewdfilter; 
 
import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.HashSet; 
import java.util.List; 
import java.util.Map; 
import java.util.Set; 
 
import org.andy.sensitivewdfilter.util.BCConvert; 
 
/** 
 * 創(chuàng)建時間:2016年8月30日 下午3:01:12 
 * 
 * 思路: 創(chuàng)建一個FilterSet,枚舉了0~65535的所有char是否是某個敏感詞開頭的狀態(tài) 
 * 
 * 判斷是否是 敏感詞開頭 | | 是 不是 獲取頭節(jié)點 OK--下一個字 然后逐級遍歷,DFA算法 
 * 
 * @author andy 
 * @version 2.2 
 */ 
public class WordFilter { 
 
  private static final FilterSet set = new FilterSet(); // 存儲首字 
  private static final Map<Integer, WordNode> nodes = new HashMap<Integer, WordNode>(1024, 1); // 存儲節(jié)點 
  private static final Set<Integer> stopwdSet = new HashSet<>(); // 停頓詞 
  private static final char SIGN = '*'; // 敏感詞過濾替換 
 
  static { 
    try { 
      long a = System.nanoTime(); 
      init(); 
      a = System.nanoTime() - a; 
      System.out.println("加載時間 : " + a + "ns"); 
      System.out.println("加載時間 : " + a / 1000000 + "ms"); 
    } catch (Exception e) { 
      throw new RuntimeException("初始化過濾器失敗"); 
    } 
  } 
 
  private static void init() { 
    // 獲取敏感詞 
    addSensitiveWord(readWordFromFile("wd.txt")); 
    addStopWord(readWordFromFile("stopwd.txt")); 
  } 
 
  /** 
   * 增加敏感詞 
   * @param path 
   * @return 
   */ 
  private static List<String> readWordFromFile(String path) { 
    List<String> words; 
    BufferedReader br = null; 
    try { 
      br = new BufferedReader(new InputStreamReader(WordFilter.class.getClassLoader().getResourceAsStream(path))); 
      words = new ArrayList<String>(1200); 
      for (String buf = ""; (buf = br.readLine()) != null;) { 
        if (buf == null || buf.trim().equals("")) 
          continue; 
        words.add(buf); 
      } 
    } catch (Exception e) { 
      throw new RuntimeException(e); 
    } finally { 
      try { 
        if (br != null) 
          br.close(); 
      } catch (IOException e) { 
      } 
    } 
    return words; 
  } 
 
  /** 
   * 增加停頓詞 
   * 
   * @param words 
   */ 
  private static void addStopWord(final List<String> words) { 
    if (words != null && words.size() > 0) { 
      char[] chs; 
      for (String curr : words) { 
        chs = curr.toCharArray(); 
        for (char c : chs) { 
          stopwdSet.add(charConvert(c)); 
        } 
      } 
    } 
  } 
 
  /** 
   * 添加DFA節(jié)點 
   * @param words 
   */ 
  private static void addSensitiveWord(final List<String> words) { 
    if (words != null && words.size() > 0) { 
      char[] chs; 
      int fchar; 
      int lastIndex; 
      WordNode fnode; // 首字母節(jié)點 
      for (String curr : words) { 
        chs = curr.toCharArray(); 
        fchar = charConvert(chs[0]); 
        if (!set.contains(fchar)) {// 沒有首字定義 
          set.add(fchar);// 首字標(biāo)志位 可重復(fù)add,反正判斷了,不重復(fù)了 
          fnode = new WordNode(fchar, chs.length == 1); 
          nodes.put(fchar, fnode); 
        } else { 
          fnode = nodes.get(fchar); 
          if (!fnode.isLast() && chs.length == 1) 
            fnode.setLast(true); 
        } 
        lastIndex = chs.length - 1; 
        for (int i = 1; i < chs.length; i++) { 
          fnode = fnode.addIfNoExist(charConvert(chs[i]), i == lastIndex); 
        } 
      } 
    } 
  } 
 
  /** 
   * 過濾判斷 將敏感詞轉(zhuǎn)化為成屏蔽詞 
   * @param src 
   * @return 
   */ 
  public static final String doFilter(final String src) { 
    char[] chs = src.toCharArray(); 
    int length = chs.length; 
    int currc; 
    int k; 
    WordNode node; 
    for (int i = 0; i < length; i++) { 
      currc = charConvert(chs[i]); 
      if (!set.contains(currc)) { 
        continue; 
      } 
      node = nodes.get(currc);// 日 2 
      if (node == null)// 其實不會發(fā)生,習(xí)慣性寫上了 
        continue; 
      boolean couldMark = false; 
      int markNum = -1; 
      if (node.isLast()) {// 單字匹配(日) 
        couldMark = true; 
        markNum = 0; 
      } 
      // 繼續(xù)匹配(日你/日你妹),以長的優(yōu)先 
      // 你-3 妹-4 夫-5 
      k = i; 
      for (; ++k < length;) { 
        int temp = charConvert(chs[k]); 
        if (stopwdSet.contains(temp)) 
          continue; 
        node = node.querySub(temp); 
        if (node == null)// 沒有了 
          break; 
        if (node.isLast()) { 
          couldMark = true; 
          markNum = k - i;// 3-2 
        } 
      } 
      if (couldMark) { 
        for (k = 0; k <= markNum; k++) { 
          chs[k + i] = SIGN; 
        } 
        i = i + markNum; 
      } 
    } 
 
    return new String(chs); 
  } 
   
  /** 
   * 是否包含敏感詞 
   * @param src 
   * @return 
   */ 
  public static final boolean isContains(final String src) { 
    char[] chs = src.toCharArray(); 
    int length = chs.length; 
    int currc; 
    int k; 
    WordNode node; 
    for (int i = 0; i < length; i++) { 
      currc = charConvert(chs[i]); 
      if (!set.contains(currc)) { 
        continue; 
      } 
      node = nodes.get(currc);// 日 2 
      if (node == null)// 其實不會發(fā)生,習(xí)慣性寫上了 
        continue; 
      boolean couldMark = false; 
      if (node.isLast()) {// 單字匹配(日) 
        couldMark = true; 
      } 
      // 繼續(xù)匹配(日你/日你妹),以長的優(yōu)先 
      // 你-3 妹-4 夫-5 
      k = i; 
      for (; ++k < length;) { 
        int temp = charConvert(chs[k]); 
        if (stopwdSet.contains(temp)) 
          continue; 
        node = node.querySub(temp); 
        if (node == null)// 沒有了 
          break; 
        if (node.isLast()) { 
          couldMark = true; 
        } 
      } 
      if (couldMark) { 
        return true; 
      } 
    } 
 
    return false; 
  } 
 
  /** 
   * 大寫轉(zhuǎn)化為小寫 全角轉(zhuǎn)化為半角 
   * 
   * @param src 
   * @return 
   */ 
  private static int charConvert(char src) { 
    int r = BCConvert.qj2bj(src); 
    return (r >= 'A' && r <= 'Z') ? r + 32 : r; 
  } 
 
} 

其中:

isContains :是否包含敏感詞
doFilter:過濾敏感詞

2、WordNode敏感詞節(jié)點

package org.andy.sensitivewdfilter; 
 
import java.util.LinkedList; 
import java.util.List; 
 
/** 
 * 創(chuàng)建時間:2016年8月30日 下午3:07:45 
 * 
 * @author andy 
 * @version 2.2 
 */ 
public class WordNode { 
 
  private int value; // 節(jié)點名稱 
 
  private List<WordNode> subNodes; // 子節(jié)點 
 
  private boolean isLast;// 默認(rèn)false 
 
  public WordNode(int value) { 
    this.value = value; 
  } 
 
  public WordNode(int value, boolean isLast) { 
    this.value = value; 
    this.isLast = isLast; 
  } 
 
  /** 
   * 
   * @param subNode 
   * @return 就是傳入的subNode 
   */ 
  private WordNode addSubNode(final WordNode subNode) { 
    if (subNodes == null) 
      subNodes = new LinkedList<WordNode>(); 
    subNodes.add(subNode); 
    return subNode; 
  } 
 
  /** 
   * 有就直接返回該子節(jié)點, 沒有就創(chuàng)建添加并返回該子節(jié)點 
   * 
   * @param value 
   * @return 
   */ 
  public WordNode addIfNoExist(final int value, final boolean isLast) { 
    if (subNodes == null) { 
      return addSubNode(new WordNode(value, isLast)); 
    } 
    for (WordNode subNode : subNodes) { 
      if (subNode.value == value) { 
        if (!subNode.isLast && isLast) 
          subNode.isLast = true; 
        return subNode; 
      } 
    } 
    return addSubNode(new WordNode(value, isLast)); 
  } 
 
  public WordNode querySub(final int value) { 
    if (subNodes == null) { 
      return null; 
    } 
    for (WordNode subNode : subNodes) { 
      if (subNode.value == value) 
        return subNode; 
    } 
    return null; 
  } 
 
  public boolean isLast() { 
    return isLast; 
  } 
 
  public void setLast(boolean isLast) { 
    this.isLast = isLast; 
  } 
 
  @Override 
  public int hashCode() { 
    return value; 
  } 
 
} 

三、測試結(jié)果

項目包含敏感詞庫,源碼,停頓詞庫等,只需運(yùn)行maven打jar包直接可運(yùn)行。

項目源碼:sensitivewd-filter_jb51.rar

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 帶你了解Java數(shù)據(jù)結(jié)構(gòu)和算法之哈希表

    帶你了解Java數(shù)據(jù)結(jié)構(gòu)和算法之哈希表

    這篇文章主要為大家介紹了Java數(shù)據(jù)結(jié)構(gòu)和算法之哈希表,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • Java中的Redis是什么意思

    Java中的Redis是什么意思

    Redis是一個非常強(qiáng)大的工具,它可以用來實現(xiàn)很多有趣的應(yīng)用,還可以使用Redis來實現(xiàn)分布式鎖,這樣你就可以在多線程或多進(jìn)程的環(huán)境下同步代碼,這篇文章主要介紹了Java中的Redis是什么意思,需要的朋友可以參考下
    2023-08-08
  • java中final與finally的使用介紹

    java中final與finally的使用介紹

    本篇文章介紹了,在java中final與finally的使用。需要的朋友參考下
    2013-04-04
  • java桌球小游戲 小球任意角度碰撞

    java桌球小游戲 小球任意角度碰撞

    這篇文章主要為大家詳細(xì)介紹了java桌球小游戲,小球任意角度碰撞,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • Springboot使用pdfbox提取PDF圖片的代碼示例

    Springboot使用pdfbox提取PDF圖片的代碼示例

    PDFBox是一個用于創(chuàng)建和處理PDF文檔的Java庫,它可以使用Java代碼創(chuàng)建、讀取、修改和提取PDF文檔中的內(nèi)容,本文就給大家介紹Springboot如何使用pdfbox提取PDF圖片,感興趣的同學(xué)可以借鑒參考
    2023-06-06
  • mybatis中association和collection的使用與區(qū)別

    mybatis中association和collection的使用與區(qū)別

    在 MyBatis 中,<association>?和?<collection>?是用于配置結(jié)果映射中關(guān)聯(lián)關(guān)系的兩個元素,本文主要介紹了mybatis中<association>和<collection>的使用與區(qū)別,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • Project?Reactor?響應(yīng)式范式編程

    Project?Reactor?響應(yīng)式范式編程

    這篇文章主要為大家介紹了Project?Reactor?響應(yīng)式范式編程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • SpringCloud @FeignClient注入Spring容器原理分析

    SpringCloud @FeignClient注入Spring容器原理分析

    本文詳細(xì)分析了Spring Boot中@FeignClient注解的掃描和注入過程,重點探討了@EnableFeignClients注解的工作原理,通過源碼分析,揭示了@EnableFeignClients如何通過@Import注解和FeignClientsRegistrar類實現(xiàn)bean定義的加載
    2024-12-12
  • Java實現(xiàn)簡單的貪吃蛇小游戲

    Java實現(xiàn)簡單的貪吃蛇小游戲

    這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)簡單的貪吃蛇小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • java發(fā)送email一般步驟(實例講解)

    java發(fā)送email一般步驟(實例講解)

    下面小編就為大家?guī)硪黄猨ava發(fā)送email一般步驟(實例講解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09

最新評論

兴义市| 鹤峰县| 扶沟县| 清水河县| 信宜市| 瓦房店市| 民县| 桦南县| 亚东县| 莫力| 汶上县| 东乡族自治县| 五寨县| 灵丘县| 金乡县| 犍为县| 思茅市| 扶绥县| 罗田县| 重庆市| 玉山县| 石狮市| 中西区| 宣汉县| 祁东县| 凉山| 诏安县| 通渭县| 霞浦县| 内丘县| 济源市| 家居| 玉山县| 临湘市| 陆丰市| 大田县| 天柱县| 九龙坡区| 林甸县| 南溪县| 武强县|