字典樹算法詳解


字典樹,又稱單詞查找樹,Trie樹,是一種樹形結構,哈希表的一個變種。用於統計,排序和保存大量的字符串(也可以保存其的)。
優點就是利用公共的前綴來節約存儲空間。在這舉個簡單的例子:比如說我們想儲存3個單詞,nyist、nyistacm、nyisttc。如果只是
單純的按照以前的字符數組存儲的思路來存儲的話,那麼我們需要定義三個字符串數組。但是如果我們用字典樹的話,只需要定義
一個樹就可以了。在這裏我們就可以看到字典樹的優勢了。
)

基本的操作

定義(即定義結點)

struct node{  
    int cnt;  
    struct node *next[26];  
    node(){  
        cnt=0;  
        memset(next,0,sizeof(next));  
    }  
};

next是表示每層有多少種類的數,如果只是小寫字母,則26即可,若改爲大小寫字母,則是52,若再加上數字,則是62了,這裏根據題意來確定。
cnt可以表示一個字典樹到此有多少相同前綴的數目,這裏根據需要應當學會自由變化。

插入(即建樹過程)

構建Trie樹的基本算法也很簡單,無非是逐一把每則單詞的每個字母插入Trie。插入前先看前綴是否存在。如果存在,就共享,否則
創建對應的節點和邊。比如要插入單詞add(已經插入了單詞“ad”),就有下面幾步:

  • 考察前綴"a",發現邊a已經存在。於是順着邊a走到節點a。
  • 考察剩下的字符串"dd"的前綴"d",發現從節點a出發,已經有邊d存在。於是順着邊d走到節點ad
  • 考察最後一個字符"d",這下從節點ad出發沒有邊d了,於是創建節點ad的子節點add,並把邊ad->add標記爲d。
void buildtrie(char *s){  
    node *p = root;  
    node *tmp = NULL;  
    int l = strlen(s);  
    for(int i = 0; i < l; ++i){  
        if(p->next[s[i]-'a'] == NULL){  
            tmp = new node;  
            p->next[s[i]-'a'] = tmp;  
        }  
        p = p->next[s[i]-'a'];  
        p->cnt++;  
    }  
}

查找

1、每次從根結點開始進行搜索;
2、取要查找關鍵詞的第一個字母,並根據該字母選擇對應的子樹並轉到該子樹繼續進行檢索;
3、在相應的子樹上,取得要查找關鍵詞的第二個字母,並進一步選擇對應的子樹進行檢索; 
4、迭代剛纔過程。。。
5、直到在某個結點處:
——關鍵詞的所有字母都被取出,則讀取附在該結點上的信息,即完成查找。
——該結點沒有任何信息,則輸出該關鍵詞不在此字典樹裏。

void findtrie(char *s){  
    node *p = root;  
    int l = strlen(s);  
    for(int i = 0; i < l; ++i){
        if(p->next[s[i]-'a'] == NULL){
            printf("0\n");  
            return;  
        }  
        p = p->next[s[i]-'a'];  
    }
    printf("%d\n",p->cnt);  
}

釋放內存

有些題目,數據比較大,需要查詢完之後釋放內存(比如:hdu1671 Phone List)
遞歸釋放內存:

void del(node *root) {
    for (int i = 0; i < 26; i++)
        if (root->next[i])
            del(root->next[i]);
    delete (root);
}

注意事項

1.用G++交會出現Memory Limit Exceeded(就算釋放了內存,還是Memory Limit Exceeded)
2.根結點要初始化root=new node;

練習

hdu 1251 統計難題
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1251
解題思路:http://blog.csdn.net/piaocoder/article/details/41552691
hdu 2072 單詞數
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2072
解題思路:http://blog.csdn.net/piaocoder/article/details/41902793
hdu 1671 Phone List
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1671
解題思路:http://blog.csdn.net/piaocoder/article/details/47951011
POJ 2001 Shortest Prefixes
題目鏈接:http://poj.org/problem?id=2001
解題思路:http://blog.csdn.net/piaocoder/article/details/47731321
POJ 2418 Hardwood Species
題目鏈接:http://poj.org/problem?id=2418
解題思路:http://blog.csdn.net/piaocoder/article/details/47731453
POJ 2503 Babelfish
題目鏈接:http://poj.org/problem?id=2503
解題思路:http://blog.csdn.net/piaocoder/article/details/47731701

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章