Golang實現(xiàn)DFA算法對敏感詞過濾功能
什么是DFA算法
DFA全稱:Deterministic Finite Automaton,翻譯過來就是確定性有限自動機,其特征是,有一個有限狀態(tài)集合和一些從一個狀態(tài)通向另一個狀態(tài)的邊,每條邊上標記有一個符號,其中一個狀態(tài)是初態(tài),某些狀態(tài)是終態(tài),但是確定性有窮自動機不會從同一狀態(tài)觸發(fā)的兩個邊標志由相同的符號。
通俗的講DFA算法就是把你要匹配的做成一顆字典樹,然后對你輸入的內(nèi)容進行匹配的過程
如何構(gòu)建這顆字典樹呢
這是一顆簡單字典樹的,我們的第一步就是構(gòu)建出一個這樣的包含敏感詞的樹
下面我說一下構(gòu)建過程
每個節(jié)點的結(jié)構(gòu)
// 定義一個Node結(jié)構(gòu)體,代表DFA的一個節(jié)點。 type Node struct { End bool // End字段表示是否為一個單詞的結(jié)束。 Next map[rune]*Node // Next字段是一個映射,用于存儲此節(jié)點的所有子節(jié)點。 }
// 定義一個DFAMatcher結(jié)構(gòu)體,代表一個完整的DFA。 type DFAMatcher struct { replaceChar rune // replaceChar字段是替換敏感詞的字符。 root *Node // root字段是DFA的根節(jié)點。 }
我們要先創(chuàng)捷出一個root節(jié)點,在root節(jié)點中是不存放數(shù)據(jù)的
//創(chuàng)建出一個DFA樹的根節(jié)點實例 func NewDFAMather() *DFAMatcher { return &DFAMatcher{ root: &Node{ End: false, }, } }
在確定完節(jié)點的結(jié)構(gòu)后,我們需要跟據(jù)敏感詞來構(gòu)建這顆字典樹
// Build方法用于構(gòu)建DFA,它會將提供的所有單詞添加到DFA中。 func (d *DFAMatcher) Build(words []string) { for _, item := range words { // 遍歷提供的所有單詞。 d.root.AddWord(item) // 將每一個單詞添加到DFA的根節(jié)點。 } } // AddWord方法用于向當前節(jié)點添加一個單詞。 // 這個方法會遍歷單詞的每一個字符,并為每一個字符添加一個子節(jié)點。 func (n *Node) AddWord(word string) { node := n // 從當前節(jié)點開始。 chars := []rune(word) // 將字符串轉(zhuǎn)化為rune類型的切片,以便處理Unicode字符。 for index, _ := range chars { // 遍歷單詞的每一個字符。 node = node.AddChild(chars[index]) // 遞歸地為每一個字符添加子節(jié)點。 } node.End = true // 設(shè)置最后一個節(jié)點為單詞的結(jié)束。 } // AddChild方法向當前節(jié)點添加一個子節(jié)點。 // 如果子節(jié)點已經(jīng)存在,它將不會被重復添加。 func (n *Node) AddChild(c rune) *Node { if n.Next == nil { // 如果Next字段為nil,則初始化一個映射。 n.Next = make(map[rune]*Node) } //檢查字符c是否已經(jīng)是當前節(jié)點的子節(jié)點。 if next, ok := n.Next[c]; ok { // 如果ok為true,則字符c已經(jīng)是當前節(jié)點的子節(jié)點,直接返回該子節(jié)點。 return next } else { // 否則,創(chuàng)建一個新的節(jié)點,并將其設(shè)置為當前節(jié)點的子節(jié)點。 n.Next[c] = &Node{ End: false, Next: nil, } return n.Next[c] // 返回新創(chuàng)建的子節(jié)點。 } }
根據(jù)上面的代碼就可一構(gòu)建出一顆包含你傳入的敏感詞的樹,在這顆樹種根節(jié)點不存放數(shù)據(jù)
過濾關(guān)鍵詞
下面就是跟據(jù)你傳入的內(nèi)容來過濾敏感詞了,你可以把敏感詞替換成其他字符,也可以統(tǒng)計敏感詞的個數(shù),這就看你自己需要什么了
下面是代碼實現(xiàn)
// Match方法用于在文本中查找并替換敏感詞。 // 它返回找到的敏感詞列表和替換后的文本。 func (d *DFAMatcher) Match(text string) (sensitiveWords []string, replaceText string) { if d.root == nil { // 如果DFA是空的,直接返回原始文本。 return nil, text } textChars := []rune(text) // 將文本轉(zhuǎn)化為rune類型的切片,以便處理Unicode字符。 textCharsCopy := make([]rune, len(textChars)) // 創(chuàng)建一個文本字符的副本,用于替換敏感詞。 copy(textCharsCopy, textChars) // 復制原始文本字符到副本。 length := len(textChars) // 獲取文本的長度。 for i := 0; i < length; i++ { // 遍歷文本的每一個字符。 // 在DFA樹中查找當前字符對應(yīng)的子節(jié)點 temp := d.root.FindChild(textChars[i]) if temp == nil { continue // 如果不存在匹配,繼續(xù)檢查下一個字符 } j := i + 1 // 遍歷文本中的字符,查找匹配的敏感詞,第一個匹配上了,就進行后面的向下匹配 for ; j < length && temp != nil; j++ { if temp.End { // 如果找到一個敏感詞,將其添加到結(jié)果列表中,并在副本中替換為指定字符 sensitiveWords = append(sensitiveWords, string(textChars[i:j])) replaceRune(textCharsCopy, '*', i, j) //替換敏感詞 } temp = temp.FindChild(textChars[j]) } // 處理文本末尾的情況,如果末尾是一個完整的敏感詞,添加到結(jié)果列表中,并在副本中替換為指定字符 if j == length && temp != nil && temp.End { sensitiveWords = append(sensitiveWords, string(textChars[i:length])) replaceRune(textCharsCopy, '*', i, length) } } return sensitiveWords, string(textCharsCopy) // 返回匹配到的敏感詞列表和替換后的文本 } // FindChild方法用于在當前節(jié)點的子節(jié)點中查找一個特定的子節(jié)點。 func (n *Node) FindChild(c rune) *Node { if n.Next == nil { // 如果Next字段為nil,則直接返回nil。 return nil } //檢查字符c是否是當前節(jié)點的子節(jié)點。 if _, ok := n.Next[c]; ok { // 如果ok為true,則字符c是當前節(jié)點的子節(jié)點,返回該子節(jié)點。 return n.Next[c] } return nil // 否則,返回nil。 } //替換掉文章中出現(xiàn)的關(guān)鍵詞 func replaceRune(chars []rune, replaceChar rune, begin int, end int) { for i := begin; i < end; i++ { chars[i] = replaceChar } }
以上就是使用Golang代碼實現(xiàn)了一個簡單的DFA算法過濾敏感詞的一個算法,這個算法相對于其他的性能更好,匹配更快。
到此這篇關(guān)于Golang實現(xiàn)DFA算法對敏感詞過濾功能的文章就介紹到這了,更多相關(guān)Golang敏感詞過濾內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang實現(xiàn)自己的Redis(有序集合跳表)實例探究
這篇文章主要為大家介紹了Golang實現(xiàn)自己的Redis(有序集合跳表)實例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2024-01-01Go語言使用defer+recover解決panic導致程序崩潰的問題
如果協(xié)程出現(xiàn)了panic,就會造成程序的崩潰,這時可以在goroutine中使用recover來捕獲panic,進行處理,本文就詳細的介紹一下,感興趣的可以了解一下2021-09-09Go語言Elasticsearch數(shù)據(jù)清理工具思路詳解
這篇文章主要介紹了Go語言Elasticsearch數(shù)據(jù)清理工具思路詳解,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-10-10