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)容進行匹配的過程
如何構建這顆字典樹呢
這是一顆簡單字典樹的,我們的第一步就是構建出一個這樣的包含敏感詞的樹

下面我說一下構建過程
每個節(jié)點的結(jié)構
// 定義一個Node結(jié)構體,代表DFA的一個節(jié)點。
type Node struct {
End bool // End字段表示是否為一個單詞的結(jié)束。
Next map[rune]*Node // Next字段是一個映射,用于存儲此節(jié)點的所有子節(jié)點。
}// 定義一個DFAMatcher結(jié)構體,代表一個完整的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é)構后,我們需要跟據(jù)敏感詞來構建這顆字典樹
// Build方法用于構建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 // 設置最后一個節(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é)點,并將其設置為當前節(jié)點的子節(jié)點。
n.Next[c] = &Node{
End: false,
Next: nil,
}
return n.Next[c] // 返回新創(chuàng)建的子節(jié)點。
}
}根據(jù)上面的代碼就可一構建出一顆包含你傳入的敏感詞的樹,在這顆樹種根節(jié)點不存放數(shù)據(jù)
過濾關鍵詞
下面就是跟據(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樹中查找當前字符對應的子節(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)的關鍵詞
func replaceRune(chars []rune, replaceChar rune, begin int, end int) {
for i := begin; i < end; i++ {
chars[i] = replaceChar
}
}以上就是使用Golang代碼實現(xiàn)了一個簡單的DFA算法過濾敏感詞的一個算法,這個算法相對于其他的性能更好,匹配更快。
到此這篇關于Golang實現(xiàn)DFA算法對敏感詞過濾功能的文章就介紹到這了,更多相關Golang敏感詞過濾內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Golang實現(xiàn)自己的Redis(有序集合跳表)實例探究
這篇文章主要為大家介紹了Golang實現(xiàn)自己的Redis(有序集合跳表)實例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2024-01-01
Go語言使用defer+recover解決panic導致程序崩潰的問題
如果協(xié)程出現(xiàn)了panic,就會造成程序的崩潰,這時可以在goroutine中使用recover來捕獲panic,進行處理,本文就詳細的介紹一下,感興趣的可以了解一下2021-09-09
Go語言Elasticsearch數(shù)據(jù)清理工具思路詳解
這篇文章主要介紹了Go語言Elasticsearch數(shù)據(jù)清理工具思路詳解,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-10-10

