日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

过滤敏感词

發布時間:2023/12/10 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 过滤敏感词 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1,什么是前綴樹

  • 根節點沒有數據,每個節點只有一個數據
  • 每個分枝都是一個敏感詞
  • 每個節點所包含的子節點不相同

例圖:

2、前綴樹過濾敏感詞的思路

  • 首先我們需要三個指針,指針1指向根節點,指針2和指針3指向我們要過濾的句子的第一個字符,開始我們先看指針2和指針3指向的第一個字符是否是前綴樹根節點的子節點,如果是,執行步驟2,如果不是執行步驟5
  • 指針3往后移動看下一個字符是否在前綴樹中如果在,執行步驟3,如果不在執行步驟4
  • 看這個字符是否是敏感詞的最后一個字,如果是替換指針2和指針3范圍內的字符,指針3向后移動一位,然后讓指針2和指針3指向同一個字符,如果不是繼續執行步驟2
  • 指針2向后移動一位,然后讓指針3和指針2指向同一個字符 ,然后執行步驟1
  • 指針2和指針3同時向后移動,執行步驟1
  • 例圖:
    -

    3、代碼實現

  • 定義前綴樹(我們創建一個工具類來實現過濾敏感詞的功能,前綴樹被我定義在工具類的內部)
  • @Component public class SensitiveFilter {// 前綴樹private class TrieNode {// 關鍵詞結束標識private boolean isKeywordEnd = false;// 子節點(key是下級字符,value是下級節點)private Map<Character, TrieNode> subNodes = new HashMap<>();public boolean isKeywordEnd() {return isKeywordEnd;}public void setKeywordEnd(boolean keywordEnd) {isKeywordEnd = keywordEnd;}// 添加子節點public void addSubNode(Character c, TrieNode node) {subNodes.put(c, node);}// 獲取子節點public TrieNode getSubNode(Character c) {return subNodes.get(c);}}}
  • 根據敏感詞,初始化前綴樹
  • @Component public class SensitiveFilter {private static final Logger logger = LoggerFactory.getLogger(SensitiveFilter.class);// 替換符private static final String REPLACEMENT = "***";// 根節點private TrieNode rootNode = new TrieNode();@PostConstructpublic void init() {try (InputStream is = this.getClass().getClassLoader().getResourceAsStream("sensitive-words.txt");BufferedReader reader = new BufferedReader(new InputStreamReader(is));) {String keyword;while ((keyword = reader.readLine()) != null) {// 添加到前綴樹this.addKeyword(keyword);}} catch (IOException e) {logger.error("加載敏感詞文件失敗: " + e.getMessage());}}// 將一個敏感詞添加到前綴樹中private void addKeyword(String keyword) {TrieNode tempNode = rootNode;for (int i = 0; i < keyword.length(); i++) {char c = keyword.charAt(i);TrieNode subNode = tempNode.getSubNode(c);if (subNode == null) {// 初始化子節點subNode = new TrieNode();tempNode.addSubNode(c, subNode);}// 指向子節點,進入下一輪循環tempNode = subNode;// 設置結束標識if (i == keyword.length() - 1) {tempNode.setKeywordEnd(true);}}}// 前綴樹private class TrieNode {// 關鍵詞結束標識private boolean isKeywordEnd = false;// 子節點(key是下級字符,value是下級節點)private Map<Character, TrieNode> subNodes = new HashMap<>();public boolean isKeywordEnd() {return isKeywordEnd;}public void setKeywordEnd(boolean keywordEnd) {isKeywordEnd = keywordEnd;}// 添加子節點public void addSubNode(Character c, TrieNode node) {subNodes.put(c, node);}// 獲取子節點public TrieNode getSubNode(Character c) {return subNodes.get(c);}}}
  • 編寫過濾敏感詞的方法
  • @Component public class SensitiveFilter {private static final Logger logger = LoggerFactory.getLogger(SensitiveFilter.class);// 替換符private static final String REPLACEMENT = "***";// 根節點private TrieNode rootNode = new TrieNode();@PostConstructpublic void init() {try (InputStream is = this.getClass().getClassLoader().getResourceAsStream("sensitive-words.txt");BufferedReader reader = new BufferedReader(new InputStreamReader(is));) {String keyword;while ((keyword = reader.readLine()) != null) {// 添加到前綴樹this.addKeyword(keyword);}} catch (IOException e) {logger.error("加載敏感詞文件失敗: " + e.getMessage());}}// 將一個敏感詞添加到前綴樹中private void addKeyword(String keyword) {TrieNode tempNode = rootNode;for (int i = 0; i < keyword.length(); i++) {char c = keyword.charAt(i);TrieNode subNode = tempNode.getSubNode(c);if (subNode == null) {// 初始化子節點subNode = new TrieNode();tempNode.addSubNode(c, subNode);}// 指向子節點,進入下一輪循環tempNode = subNode;// 設置結束標識if (i == keyword.length() - 1) {tempNode.setKeywordEnd(true);}}}/*** 過濾敏感詞** @param text 待過濾的文本* @return 過濾后的文本*/public String filter(String text) {if (StringUtils.isBlank(text)) {return null;}// 指針1TrieNode tempNode = rootNode;// 指針2int begin = 0;// 指針3int position = 0;// 結果StringBuilder sb = new StringBuilder();while (position < text.length()) {char c = text.charAt(position);// 跳過符號if (isSymbol(c)) {// 若指針1處于根節點,將此符號計入結果,讓指針2向下走一步if (tempNode == rootNode) {sb.append(c);begin++;}// 無論符號在開頭或中間,指針3都向下走一步position++;continue;}// 檢查下級節點tempNode = tempNode.getSubNode(c);if (tempNode == null) {// 以begin開頭的字符串不是敏感詞sb.append(text.charAt(begin));// 進入下一個位置position = ++begin;// 重新指向根節點tempNode = rootNode;} else if (tempNode.isKeywordEnd()) {// 發現敏感詞,將begin~position字符串替換掉sb.append(REPLACEMENT);// 進入下一個位置begin = ++position;// 重新指向根節點tempNode = rootNode;} else {// 檢查下一個字符position++;}}// 將最后一批字符計入結果sb.append(text.substring(begin));return sb.toString();}// 判斷是否為符號private boolean isSymbol(Character c) {// 0x2E80~0x9FFF 是東亞文字范圍return !CharUtils.isAsciiAlphanumeric(c) && (c < 0x2E80 || c > 0x9FFF);}// 前綴樹private class TrieNode {// 關鍵詞結束標識private boolean isKeywordEnd = false;// 子節點(key是下級字符,value是下級節點)private Map<Character, TrieNode> subNodes = new HashMap<>();public boolean isKeywordEnd() {return isKeywordEnd;}public void setKeywordEnd(boolean keywordEnd) {isKeywordEnd = keywordEnd;}// 添加子節點public void addSubNode(Character c, TrieNode node) {subNodes.put(c, node);}// 獲取子節點public TrieNode getSubNode(Character c) {return subNodes.get(c);}}}

    總結

    以上是生活随笔為你收集整理的过滤敏感词的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。