| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- package keyword
- import (
- "fmt"
- "strings"
- "unicode"
- "unicode/utf8"
- )
- var stars = []rune("****")
- // TrieNode 表示 Trie 树的节点
- type TrieNode struct {
- children map[rune]*TrieNode
- isEnd bool
- }
- // Trie 表示 Trie 树
- type Trie struct {
- root *TrieNode
- }
- // NewTrie 创建一个新的 Trie 树
- func NewTrie() *Trie {
- return &Trie{
- root: &TrieNode{
- children: make(map[rune]*TrieNode),
- },
- }
- }
- // Insert 将字符串插入到 Trie 树中
- func (t *Trie) Insert(word string) {
- node := t.root
- for _, char := range word {
- if _, exists := node.children[char]; !exists {
- node.children[char] = &TrieNode{children: make(map[rune]*TrieNode)}
- }
- node = node.children[char]
- }
- node.isEnd = true
- }
- // ReverseString 反转字符串
- func ReverseString(s string) string {
- runes := []rune(s)
- for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
- runes[i], runes[j] = runes[j], runes[i]
- }
- return string(runes)
- }
- // 第二版写法 FilterSensitiveWords 使用 Trie 树过滤敏感词
- func FilterSensitiveWords(text string, trie *Trie) string {
- var result []rune
- var lastMatchEnd int
- // 标准化文本
- text = strings.ToLower(text)
- runes := []rune(text)
- tn := len(runes)
- var pch rune
- // 遍历文本
- for i := 0; i < tn; {
- // 查找匹配
- // fmt.Printf("\ni: %d\n", i)
- node := trie.root
- j := i
- ch1 := runes[j]
- // fmt.Printf("%c", ch1)
- // fmt.Printf("text[i:]: %s \n", text[i:i+w1])
- for j < tn {
- //fmt.Printf("\nj: %d\n", j)
- char := runes[j]
- if node.children[char] == nil {
- break
- }
- //fmt.Printf("%c ", char)
- node = node.children[char]
- j += 1
- ch2 := rune(0)
- samePre := false
- if j < tn {
- ch2 = runes[j]
- samePre = node.children[ch2] != nil
- }
- //检查是否有相同前缀的其他敏感词
- if node.isEnd && !samePre {
- // 匹配到敏感词,替换为*
- if unicode.Is(unicode.Arabic, char) {
- //如果当前字符是阿拉伯字符则判断单词前面和单词后面和一个字符是否为阿拉伯字符
- // fmt.Printf("ch: %c\n", ch)
- // fmt.Printf("text[j+1:]: %s\n", text[j:])
- //
- if unicode.Is(unicode.Arabic, ch2) || unicode.Is(unicode.Arabic, pch) {
- //如果也是则不过滤,这个可能是一个新词
- break
- }
- }
- result = append(result, stars...)
- lastMatchEnd = j
- break
- }
- }
- // 如果没有匹配到敏感词,保留原字符
- if j == i {
- result = append(result, ch1)
- j += 1
- } else if j != lastMatchEnd {
- result = append(result, runes[i:j]...)
- }
- pch = ch1
- i = j
- }
- return string(result)
- }
- // 第一版写法
- func FilterSensitiveWords2(text string, trie *Trie) string {
- var filteredText strings.Builder
- var lastMatchEnd int
- // 标准化文本
- text = strings.ToLower(text)
- tn := len(text)
- var pch rune
- // 遍历文本
- for i := 0; i < tn; {
- // 查找匹配
- //fmt.Printf("\ni: %d\n", i)
- node := trie.root
- j := i
- ch1, _ := utf8.DecodeRuneInString(text[j:])
- // fmt.Printf("%c", ch1)
- // fmt.Printf("text[i:]: %s \n", text[i:i+w1])
- for j < tn {
- char, width := utf8.DecodeRuneInString(text[j:])
- if node.children[char] == nil {
- break
- }
- //fmt.Printf("%c ", char)
- node = node.children[char]
- j += width
- if node.isEnd {
- // 匹配到敏感词,替换为*
- if unicode.Is(unicode.Arabic, char) {
- //如果当前字符是阿拉伯字符则判断单词前面和单词后面和一个字符是否为阿拉伯字符
- ch2, wi := utf8.DecodeRuneInString(text[j:])
- if j+wi < tn {
- // fmt.Printf("ch: %c\n", ch)
- // fmt.Printf("text[j+1:]: %s\n", text[j:])
- //
- if unicode.Is(unicode.Arabic, ch2) || unicode.Is(unicode.Arabic, pch) {
- //如果也是则不过滤,这个可能是一个新词
- // filteredText.WriteString(text[i:j])
- break
- }
- }
- }
- filteredText.WriteString(strings.Repeat("*", 4))
- lastMatchEnd = j
- break
- }
- }
- // 如果没有匹配到敏感词,保留原字符
- if j == i {
- char, width := utf8.DecodeRuneInString(text[i:])
- filteredText.WriteRune(char)
- j += width
- } else if j != lastMatchEnd {
- filteredText.WriteString(text[i:j])
- }
- pch = ch1
- i = j
- }
- return filteredText.String()
- }
- func TestMatch() {
- runes := []rune("he样s1")
- fmt.Printf("runes: %v\n", runes)
- LoadKeywordsLocal()
- //阿拉伯语序从右到左
- rt := ParseKeyword("بوسهعلىالصدر")
- //相同前缀
- // rt := keyword.ParseKeyword("بوس")
- // rt := ParseKeyword("22بوس36")
- // rt := keyword.ParseKeyword("تف")
- // rt := keyword.ParseKeyword("oمهبلseductive")
- // rt := keyword.ParseKeyword("🍎🍎🍼🍼💦💦👅👅✊🍼🍆🍆👇杨涛")
- // rt := ParseKeyword("مهبل你好 مهبل مهبل ee")
- // rt := keyword.ParseKeyword("مهبلd ee")
- fmt.Printf("rt: %v\n", rt)
- }
|