黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

數據結構之——Trie樹

系統 2391 0


????? Trie樹,又稱單詞查找樹,典型用于統計和排序大量字符串,查詢效率比哈希表高。(空間復雜度高)

它有3個基本特性:
  1)根節點不包含字符,除根節點外每一個節點都只包含一個字符。
  2)從根節點到某一節點,路徑上經過的字符連接起來,為該節點對應的字符串。
  3)每個節點的所有子節點包含的字符都不相同。

Trie的核心思想是空間換時間。利用字符串的公共前綴來降低查詢時間的開銷以達到提高效率的目的。

?

Trie樹的結構體:

    struct Trie_Node
{
	int id;//數據域
	Trie_Node *next[26];//孩子結點
	Trie_Node()
	{
		id = -1;
		memset(next,0,sizeof(next));
	}
}*root;
  

?

Trie樹的更新操作(插入、查詢某字符串的數據)

    int getNum(char *t)
{
	Trie_Node *p = root;
	int i = 0,del;
	while(t[i] != '\0')
	{
		del = t[i] - 'a';
		if(p->next[del] == NULL)
			p->next[del] = new Trie_Node();//動態建樹,也可以換成靜態
		p = p->next[del];
		i++;
	}
	if(p->id == -1)
		p->id = num++;
	return p->id;
}
  

?

POJ2513

題目大意:有n根筷子(n=250000),每根筷子兩頭涂有顏色。現在問能否將所有筷子連起來,并且每兩根筷子的連接點顏色都相同。

分析:題意不難理解,現在做一個轉換:將每種顏色作為一個結點,每根筷子兩頭的顏色之間連有一條邊。這樣,就形成了下面的圖:

數據結構之——Trie樹

?

???? 這樣問題就轉化為:要求全部走完且經過每條邊一次且僅一次,即一筆畫問題。?這就成了歐拉路的判斷:

1.判斷該圖是否連通;

2.該圖的每個點的度要么全為偶數,要么有且僅有兩個度為奇數。

判斷圖是否是連通圖,可以用并查集。計算每個點的度,就是統計單詞出現的次數。因此聯想到用Trie樹統計單詞出現的次數,每次將單詞在Trie樹中查找,若該單詞在trie樹中第一次出現,則給它一個標號(相當于hash)。

?

POJ3630(1056)

題目大意:給出n個電話號碼(n=10000),每個電話號碼長度不超過10。要求是否滿足:每個電話號碼不能是其它號碼的前綴。

分析:在Trie樹中放置一個標志位,表示從根節點到該結點是否是已經輸入的號碼。

    bool findAndInsert(char *t)
{
	Trie_Node *p = root;
	int i = 0,del;
	while(t[i] != '\0')
	{
		if(p->exist)
			return true;		//別的字符串是當前字符串的前綴
		del = t[i] - '0';
		if(p->next[del] == NULL)
		{
			p->next[del] = &node[nodeNum];
			nodeNum++;
		}
		p = p->next[del];
		i++;
	}
	for(i = 0; i < 10; i++)		//當前字符串是別的字符串的前綴
	{
		if(p->next[i] != NULL)
			return true;
	}
	p->exist = true;
	return false;
}
  

?

POJ2001

題目大意:現在人們喜歡用縮寫,比如 carbon 可以縮寫為carb,但不能縮寫為car。因為有car這個準確的單詞。給你n個單詞(n=1000),每個單詞長度不超過20。求出每個單詞的最短縮寫。

分析:在Trie樹中加入一個計數器num,表示以這個字符串為前綴的單詞有幾個。在查詢時,根據傳入的單詞一層層的往下找,找到num=1就說明這個是第一次被使用,停止輸出。

    #include <iostream>
const int MAX = 1001;
char str[MAX][21];
int nodeNum;

struct Trie_Node
{
	int num;	//to remember how many words can reach here
	Trie_Node *next[26];
	Trie_Node()
	{
		num = 0;
		memset(next,NULL,sizeof(next));
	}
};
Trie_Node node[MAX*10],head;

void insert(char *t)
{
	int i=0,del;
	Trie_Node *p = &head;
	while(t[i] != '\0')
	{
		del = t[i] - 'a';
		if(p->next[del] == NULL)
		{
			p->next[del] = &node[nodeNum];
			nodeNum++;
		}
		p->next[del]->num++;
		p = p->next[del];
		i++;
	}
}

void query(char *t)
{
	int i = 0;
	Trie_Node *p = &head;
	while(t[i] != '\0')
	{
		printf("%c",t[i]);
		p = p->next[t[i]-'a'];
		if(p->num == 1)
			break;
		i++;
	}
	printf("\n");
}

int main()
{
	int i = 0;
	nodeNum = 1;
	while(scanf("%s",str[i]) != EOF)
	{
		insert(str[i]);
		i++;
	}
	for(int j = 0; j < i; j++)
	{
		printf("%s ",str[j]);
		query(str[j]);
	}
	return 0;
}
  

?

?

?

數據結構之——Trie樹


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論