字典樹Trie

字典樹,顧名思義,就是把字典放到樹上ui

不不不,是用字典來建樹spa

把樹建成字典的樣子?指針

差很少。code

字典樹指的是某個字符串集合對應的有根樹,樹的每條邊上剛好對應一個字符,每一個頂點表明從根到該節點的路徑所對應的字符串(將全部通過的邊上的字符按照順序鏈接起來)。有時咱們也稱trie上的邊爲轉移,節點爲狀態blog

是否是讀起來很噁心字符串

其實能夠這麼理解string

字典樹就是一棵利用了字符串的公共前綴(好比gcakioi和gcakimo的前綴就是gcaki)來減小查詢時間的樹。當你查詢單詞的時候,只要沿着轉移邊查找就能夠了,而且對於每一個單詞的結尾,在字典樹上都會有標記來表示這是一整個單詞。io

舉個例子class

如今有兩個單詞gc

A:GCAKIOI

B:GCAKIMO

那麼這個字典樹大概就是這個樣子

 

很是直觀對吧

就是在相同的時候合到一塊兒,不一樣的時候分開,在單詞結尾進行標記就行了

操做實現:

1.初始化

  一棵空的trie只包含一個根節點,該點的字符指針都指向空

int ch[N][Z]//Z爲字符集大小,ch[i][j]表示節點i的j字符指向的節點
bool bo[N]//對給以i爲終止字符的節點打標記

 

2.插入

  當須要插入一個字符串S的時候,咱們令一個指針P指向根節點,而後依次掃描S中的每一個字符c

  •   若是指針P的c字符指針指向一個存在的節點Q,則令P=Q
  •        若是指針P的c字符指針指向空,則新建一個節點Q,令P的c字符指針指向Q,而後令P=Q
  •        當S中的字符掃描完畢時,在當前節點指針P上標記它是一個字符串的末尾

 

inline void build(string s,int id)
{
    int now=1,len=s.size();
    rep(i,0,len-1)
    {
        int c=s[i]-'a';
        if(!ch[now][c])
        {
            ch[now][c]=++cnt;
        }//若是尚未這個節點,就新建立一個節點 
        now=ch[now][c];//當前節點轉移過去 
    }
    bo[now]=id;//給以節點now爲終止節點的打上標記 
}

 

 

 

3.查詢

  當咱們要查詢一個字符串S在trie中是否出現時,咱們令一個指針P起初指向根節點,而後依次掃描S中的每個字符c

  •   若是指針P的c字符指針指向空,則說明S沒有被插入過trie
  •        若是指針P的c字符指針指向一個已經存在的節點Q,則令P=Q
  •        當S中的字符掃描完畢時,若當前節點P被標記爲一個字符串的末尾,則說明S在trie中已經存在,不然說明S沒有被插入過trie

 

inline bool find(char s[])
{
    int now=1,len=strlen(s),c,k;
    rep(i,0,len-1)//在字典樹上查找該單詞 
    {
        c=s[i]-'a';
        if(!ch[now][c]) return false;
        now=ch[now][c];
    }
    return true;
}

 

當字符均爲小寫字母或者大寫字母時,trie能夠當作一個26叉樹

它的空間複雜度爲O(N*C),N是節點個數,C是字符集的大小

相關文章
相關標籤/搜索