三、**實現
前幾天都看乙個敏感詞遮蔽演算法的文章,寫的挺好,順著思路寫了下去,實現了一下,演算法效率還是槓槓的。。。
利用的是單詞樹的演算法,先看看什麼叫單詞樹。單詞樹也叫trie 樹也稱為字典樹。最大的特點就是共享字串的公共字首來達到節省空間的目的。
例如,字串 "abc"和"abd"構成的單詞樹如下:
樹的根節點不存任何資料,每整個個分支代表乙個完整的字串。像 abc 和 abd 有公共字首 ab,所以我們可以共享節點 ab。如果再插入 abf,則變成這樣:
這樣看來能實現的功能就很顯而易見了,例如詞頻統計,單詞查詢,還有就是遊戲裡的敏感詞遮蔽。
來具體說說實現的思路吧。
這兩個都是同一種思路。即下面**裡的find_word_exists
函式,詞頻統計加個累計就好了。
關鍵在建立單詞樹的時候,需要新增子節點,另外還要標記單詞是否在此處是完整單詞。然後將乙個個字元插入即可。
這個稍微複雜點。即下面**裡的sensitive_word_filter
函式。
需要三個指標來遍歷實現,兩個在檢查的單詞上,乙個在單詞樹上。
1、首先指標 p1 指向 root,指標 p2 和 p3 指向字串第乙個字元
2、然後從字串的 a 開始,檢測有沒有以 a 作為字首的敏感詞,直接判斷 p1 的孩子節點中是否有 a 這個節點就可以了,顯然這裡沒有。接著把指標 p2 和 p3 向右移動一格。
3、然後從字串 b 開始查詢,看看是否有以 b 作為字首的字串,p1 的孩子節點中有 b,這時,我們把 p1 指向節點 b,p2 向右移動一格,不過,p3不動。
4、判斷 p1 的孩子節點中是否存在 p2 指向的字元c,顯然有。我們把 p1 指向節點 c,p2 向右移動一格,p3不動。
5、判斷 p1 的孩子節點中是否存在 p2 指向的字元d,這裡沒有。這意味著,不存在以字元b作為字首的敏感詞。這時我們把p2和p3都移向字元c,p1 還是還原到最開始指向 root。
6、和前面的步驟一樣,判斷有沒以 c 作為字首的字串,顯然這裡沒有,所以把 p2 和 p3 移到字元 d。
到這裡應該差不多懂了。。。後面都一樣。那開始動手實踐。
這裡的詞頻統計,單詞查詢和敏感詞遮蔽都實現了,如下;
#include #include using namespace std;
#pragma pack(1)
struct trie_node
}};#pragma pack()
class trie
~trie()
trie_node* create()
void insert(const char* str)
trie_node* next_node = _root_node;
while(*str != 0)
else
next_node = next_node->childs[index];
next_node->letter = *str;
str++;
}next_node->is_terminal = true;
}bool find_word_exists(const char* str)
trie_node* cur_node = _root_node;
dostr++;
}while (*str != 0);
return cur_node->is_terminal; /* 直接看當前是否有完整單詞的標誌 */
}void sensitive_word_filter(char* str)
char* pre = str;
char* cur = str;
trie_node* cur_node = _root_node;
do*pre = '*';
// 向後移動,重新開始單詞樹查詢
cur++;
pre = cur;
cur_node = _root_node;
continue;
}cur_node = cur_node->childs[index];
cur++;
}else
}while (*cur != 0);
return;
}void delete_trie(trie_node* node)
for (int i = 0; i < trie_node::letter_count; i++)
}delete node;
}};int main(int argc, char** ar**)
char* word = null;
if(null != ar**[1])
else
trie trie_tree = trie();
trie_tree.insert("back");
trie_tree.insert("backen");
trie_tree.insert("basic");
/*1. 詞頻統計,和單詞查詢*/
bool is_find = trie_tree.find_word_exists(word);
if(is_find)
else
/*2. 敏感詞遮蔽*/
trie_tree.sensitive_word_filter(word);
printf("word = %s\n", word);
return 0;
}
執行結果:
find word
word = ****
./a.out backhahaha
執行結果:
not find
word = ****hahaha
Trie樹(單詞查詢樹)
前言 tire樹,又稱之為字典樹或者單詞查詢樹。是一種樹形結構,是雜湊樹的變種。典型應用是用於統計 排序或儲存大量的字串 不僅限於字串 所以經常被搜尋引擎系統用於文字詞頻的統計。因為相同的字串字首會共享同一條分支,所以優點是可以利用不同字串的相同字首來減少無謂的字串比較,查詢效率比hash表 has...
Trie 單詞查詢樹
l 簡介 trie 又稱單詞查詢樹 字首樹,是一種雜湊樹的變種。應用於字串的統計與排序,經常被搜尋引擎系統用於文字詞頻統計。含有單詞 tea tree a zsu 的一棵trie l性質 n根節點不包含字元,除根節點外的每乙個節點都只包含乙個字元。n從根節點到某一節點,路徑上經過的字元連線起來,為該...
Trie 單詞查詢樹
l 簡介 trie 又稱單詞查詢樹 字首樹,是一種雜湊樹的變種。應用於字串的統計與排序,經常被搜尋引擎系統用於文字詞頻統計。含有單詞 tea tree a zsu 的一棵trie l性質n 根節點不包含字元,除根節點外的每乙個節點都只包含乙個字元。n 從根節點到某一節點,路徑上經過的字元連線起來,為...