網絡常用敏感詞過濾方法


 一、基礎概念介紹

  DFA全稱為:Deterministic Finite Automaton,即確定有窮自動機。其特征為:有一個有限狀態集合和一些從一個狀態通向另一個狀態的邊,每條邊上標記有一個符號,其中一個狀態是初態,某些狀態是終態。但不同於不確定的有限自動機,DFA中不會有從同一狀態出發的兩條邊標志有相同的符號。

       NFA全稱為:Non-Deeterministic Finite State Automata,即不確定的有窮自動機: 對一個輸入符號,有兩種或兩種以上可能對狀態,所以是不確定的。

      

二、Trie tree算法

       Trie tree,又稱字典樹、單詞查找樹,是一種樹形結構,用於保存大量的字符串,是DFA算法中最常見的一種。它的優點是:利用字符串的公共前綴來節約存儲空間。

       將abject、ablaze、able、abound、about、accent、accept、best、bestow、bet……生成Trie tree圖,如下所示:

 

 

  Trie tree類定義如下:

1     public class Trietree
2     {
3         public bool End;    //當前節點是否有匹配到的字符串
4         public List<string> Results;    // 匹配到的字符串集合
5         public Dictionary<char, Trietree > Nodes;    //子節點
6     }

 

三、AC自動機算法

       AC自動機是在trie tree基礎上進行優化的算法。即在tried tree的類上增加一個failure指針,如果當前點匹配失敗,則將指針轉移到failure指針指向的地方,這樣就不用回溯,而可以路匹配下去了。

       例如使用上文生成的tried tree進行匹配【abestp】,

 

       第一次,從a開始匹配,從左到右只能匹配到了ab。

       第二次,從b開始匹配,從左到右匹配到了best,並且成功匹配了。

      

       在這個案例中,出現了算法回溯,如第一次匹配失敗后,第二次還是從根節點匹配開始查找下一個節點,這就是回溯。

       AC自動機增加failure指針后,在第一次匹配失敗時,就通過failure指針來到了第二次的b節點,減少回溯,從而優化性能。

 

AC自動機類定義如下:

1     public class ACTrietree
2     {
3         public bool End;    //當前節點是否有匹配到的字符串
4         public List<string> Results;    // 匹配到的字符串集合
5         public Dictionary<char, ACTrietree> Nodes;  //子節點
6         public ACTrietree Failure; // Failure指針,匹配失敗后,使用此值進行下一次匹配
7         public ACTrietree Parent; //構造 Failure時 輔助用的
8     }

       AC自動機構造方法太多了,此文不再闡述。

 

四、AC自動機的幾種改良

       AC自動機算法在算法理論上是無法再進行優化的,但可以在代碼實現中優化:

       1、Results集合,改用List<int>,做成索引集,就會減少內存使用量。

       2、Nodes字典使用的是Dictionary<>類,也是內存使用大戶,並且Dictionary<>類查詢采用的是hash查找,改用自定義Dictionary類使用二分查找。

       3、構建AC自動機比較費時,當關鍵字太多時,會有明顯感覺,可以使用序列化保存到文件,第二次加載文件就很快了。

       4、查詢時,使用數組化查詢比使用類查詢快,常用的方法就是將ACTrietree結構轉成5組數組,分別是basePtr、nextPtr、check、failure、resultIndex五組。

 

后記:

       敏感詞過濾是一個復雜工程,學會AC自動機算法,只能說已經達到敏感詞過濾的基礎。

      

       不建議將Trietree轉成double array trie,原因很簡單,數組的長度是有最大限制的,如在C#代碼中定入下面代碼會報“Array dimensions exceeded supported range“

              int[] c =new int[0x7fffffff];

       將數組數量壓得越少,數組的最大長度越容易達到最大限制。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM