字典樹詳解

字典樹詳解

字典樹是一種用於統計和排序大量的字符串的數據結構。它的原理是把具有相同前綴的字符建立一顆樹。

例如,我們有字符acdr,aced,bde,asd,ceed,asdr,frt進行建樹的話應該是這樣:
在這裏插入圖片描述
字典樹兩個基本操作是:1.建樹2.查詢

1.建樹

建樹的方式兩種一種是用數組建樹,一種是鏈表建樹。在acm和oi中常用的建樹方式是數組建樹,在這裏我們主要講解一下數組建樹。二者建樹的思想是一致的

  假定給你n個字符,將每個字符插入樹中其實就算完成了建樹的過程。我們用二維數組tire來作爲樹的儲存結構。
tire[rt][c] = index代表rt節點與index相連,且index節點代表以c字符爲結尾的一個字符串。 假定將str字符串插入字典樹中,那麼檢測當前節點rt是否與str[i]相連,如果相連的話tire[rt][str[i]] > 0,如果不相連的話tire[rt][str[i]] == 0,這時候我們應該創建一個新的節點使得rt與str[i]相連。代碼如下:

void insert(char* data)
{
	int len = strlen(data);
	rt = root;
	for(int i = 0; i < len; i++)  //建樹的過程 
	{
		int y = data[i] - 'a';
		if(tire[rt][y] == 0)   //如果rt與data[i]不相連,就創建一個新的節點使兩者相連 
		{
			tire[rt][y] = ++index;
		}
		rt = tire[rt][y];
	}
}

2.查詢

查詢過程因題目而異。
如Hdu_1251,這個題要在建樹的過程中把每一個前綴的數量統計下來
代碼如下:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define ll long long 
#define mmset(a,b) memset(a,b,sizeof(a))
using namespace std;
const int N = 1e6;
int trie[N][30], num[N] = {0};
int root = 0, index = 1;
void insert(char* data)
{
    int len = strlen(data);
    int rt = root;
    for(int i = 0; i < len; i++)
    {
        int y = data[i] - 'a';
        if(trie[rt][y] == 0)
        {
            trie[rt][y] = index++;
        }
        rt = trie[rt][y];
        num[rt]++;
    }
}
int query(char* str)
{
    int len = strlen(str);
    int rt = root;
    for(int i = 0; i < len; i++)
    {
        int y = str[i] - 'a';
        rt = trie[rt][y];
        if(rt == 0)
        {
            return 0;
        }
    }
    return num[rt];
}

int main()
{
    char word[11];
     while(gets(word))
     {
       if(word[0]==NULL)    //空行。gets讀入的回車符會自動轉換爲NULL。
             break;
         insert(word);
     }
     while(gets(word))
         printf("%d\n",query(word));
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章