JAVA使用前綴樹(shù)(Tire樹(shù))實(shí)現(xiàn)敏感詞過(guò)濾、詞典搜索
簡(jiǎn)介
有時(shí)候需要對(duì)用戶輸入的內(nèi)容進(jìn)行敏感詞過(guò)濾,或者實(shí)現(xiàn)查找文本中出現(xiàn)的詞典中的詞,用遍歷的方式進(jìn)行替換或者查找效率非常低,這里提供一個(gè)基于Trie樹(shù)的方式,進(jìn)行關(guān)鍵詞的查找與過(guò)濾,在詞典比較大的情況下效率非常高。
Trie樹(shù)
Trie樹(shù),又叫前綴樹(shù),多說(shuō)無(wú)益,直接看圖就明白了
詞典:[“豬狗”, “小狗”, “小貓”, “小豬”, “垃圾”, “狗東西”]
Tire數(shù)據(jù)結(jié)構(gòu):

code
樹(shù)節(jié)點(diǎn)Node.class
/**
* trie tree
*
* @author lovely dog
* @date 2020/10/20
*/
public class Node {
/**
* 子節(jié)點(diǎn)
*/
private Map<Character, Node> nextNodes = new HashMap<>();
public void addNext(Character key, Node node){
nextNodes.put(key, node);
}
public Node getNext(Character key){
return nextNodes.get(key);
}
public boolean isLastCharacter(){
return nextNodes.isEmpty();
}
}
搜索類TrieSearcher.class
/**
* trie tree searcher
*
* @author lovely dog
* @date 2020/10/20
*/
public class TrieSearcher {
private Node root = new Node();
/**
* 添加詞
*
* @param word 詞
*/
public void addWord(String word) {
Node tmpNode = root;
for (char c : word.toCharArray()) {
Node node = tmpNode.getNext(c);
if (null == node) {
node = new Node();
tmpNode.addNext(c, node);
}
tmpNode = node;
}
}
/**
* 替換詞
*
* @param text 待處理文本
* @param afterReplace 替換后的詞
* @return 處理后的文本
*/
public String replace(String text, String afterReplace) {
StringBuilder result = new StringBuilder(text.length());
Node tmpNode = root;
int begin = 0, pos = 0;
while (pos < text.length()) {
char c = text.charAt(pos);
tmpNode = tmpNode.getNext(c);
if (null == tmpNode) {
result.append(text.charAt(begin));
begin++;
pos = begin;
tmpNode = root;
} else if (tmpNode.isLastCharacter()) {
// 匹配完成, 進(jìn)行替換
result.append(afterReplace);
pos++;
begin = pos;
tmpNode = root;
} else {
// 匹配上向后移
pos++;
}
}
result.append(text.substring(begin));
return result.toString();
}
/**
* 查找
*
* @param text 待處理文本
* @return 統(tǒng)計(jì)數(shù)據(jù) key: word value: count
*/
public Map<String, Integer> find(String text) {
Map<String, Integer> resultMap = new HashMap<>(16);
Node tmpNode = root;
StringBuilder word = new StringBuilder();
int begin = 0, pos = 0;
while (pos < text.length()) {
char c = text.charAt(pos);
tmpNode = tmpNode.getNext(c);
if (null == tmpNode) {
begin++;
pos = begin;
tmpNode = root;
} else if (tmpNode.isLastCharacter()) {
// 匹配完成
String w = word.append(c).toString();
resultMap.put(w, resultMap.getOrDefault(w, 0) + 1);
pos++;
begin = pos;
tmpNode = root;
word = new StringBuilder();
} else {
// 匹配上向后移
word.append(c);
pos++;
}
}
return resultMap;
}
}
測(cè)試Main.class
public class Main {
public static void main(String[] args) {
TrieSearcher trieSearcher = new TrieSearcher();
Stream.of("豬狗", "小狗", "小貓", "小豬", "垃圾", "狗東西").forEach(trieSearcher::addWord);
String sentence = "你好,小狗,小豬,今天天氣真好。";
System.out.println(trieSearcher.replace(sentence, "***"));
System.out.println(trieSearcher.find(sentence));
}
}
輸出:
你好,***,***,今天天氣真好。
{小豬=1, 小狗=1}
Benchmark:
replace 1093.517 ns/op
trie 200.042 ns/op
結(jié)論
在僅有短文本和小詞典的情況下,通過(guò)性能測(cè)試可以看出前綴樹(shù)的效率很高,隨著文本和詞典的增長(zhǎng),性能提升會(huì)非常明顯。
到此這篇關(guān)于JAVA使用前綴樹(shù)(Tire樹(shù))實(shí)現(xiàn)敏感詞過(guò)濾、詞典搜索的文章就介紹到這了,更多相關(guān)JAVA前綴樹(shù)敏感詞過(guò)濾內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- JavaEE Filter敏感詞過(guò)濾的方法實(shí)例詳解
- JavaWeb中的filter過(guò)濾敏感詞匯案例詳解
- java利用DFA算法實(shí)現(xiàn)敏感詞過(guò)濾功能
- Java實(shí)現(xiàn)DFA算法對(duì)敏感詞、廣告詞過(guò)濾功能示例
- Java實(shí)戰(zhàn)之敏感詞過(guò)濾器
- Java使用DFA算法實(shí)現(xiàn)敏感詞過(guò)濾的示例代碼
- Java 過(guò)濾器實(shí)現(xiàn)敏感詞匯過(guò)濾功能
- Java數(shù)據(jù)敏感詞轉(zhuǎn)換成符號(hào)的方法詳解
- Java 敏感詞檢測(cè)工具的實(shí)現(xiàn)
相關(guān)文章
java容器類知識(shí)點(diǎn)詳細(xì)總結(jié)
這篇文章主要介紹了java容器類知識(shí)點(diǎn)詳細(xì)總結(jié),2019-06-06
詳解Spring Boot的GenericApplicationContext使用教程
這篇教程展示了如何在Spring應(yīng)用程序中使用GenericApplicationContext 。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11
Java 如何使用@Autowired注解自動(dòng)注入bean
這篇文章主要介紹了Java 使用@Autowired注解自動(dòng)注入bean的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
OpenFeign無(wú)法遠(yuǎn)程調(diào)用問(wèn)題及解決
文章介紹了在使用Feign客戶端時(shí)遇到的讀超時(shí)問(wèn)題,并分析了原因是系統(tǒng)啟動(dòng)時(shí)未先加載Nacos配置,為了解決這個(gè)問(wèn)題,建議將Nacos配置放在`bootstrap.yml`文件中,以便項(xiàng)目啟動(dòng)時(shí)優(yōu)先加載Nacos配置2024-11-11

