Tire樹(字典樹)

from:https://www.cnblogs.com/justinh/p/7716421.htmlphp

 Trie,又常常叫前綴樹,字典樹等等。它有不少變種,如後綴樹,Radix Tree/Trie,PATRICIA tree,以及bitwise版本的crit-bit tree。固然不少名字的意義其實有交叉。html

 

定義

在計算機科學中,trie,又稱前綴樹或字典樹,是一種有序樹,用於保存關聯數組,其中的鍵一般是字符串。與二叉查找樹不一樣,鍵不是直接保存在節點中,而是由節點在樹中的位置決定。一個節點的全部子孫都有相同的前綴,也就是這個節點對應的字符串,而根節點對應空字符串。通常狀況下,不是全部的節點都有對應的值,只有葉子節點和部份內部節點所對應的鍵纔有相關的值。ios

trie中的鍵一般是字符串,但也能夠是其它的結構。trie的算法能夠很容易地修改成處理其它結構的有序序列,好比一串數字或者形狀的排列。好比,bitwise trie中的鍵是一串位元,能夠用於表示整數或者內存地址c++

 

基本性質git

1,根節點不包含字符,除根節點意外每一個節點只包含一個字符。面試

2,從根節點到某一個節點,路徑上通過的字符鏈接起來,爲該節點對應的字符串。算法

3,每一個節點的全部子節點包含的字符串不相同。數組

 

優勢數據結構

能夠最大限度地減小無謂的字符串比較,故能夠用於詞頻統計和大量字符串排序。app

  跟哈希表比較:

    1,最壞狀況時間複雜度比hash表好

    2,沒有衝突,除非一個key對應多個值(除key外的其餘信息)

    3,自帶排序功能(相似Radix Sort),先序遍歷trie能夠獲得排序。

缺點

1,雖然不一樣單詞共享前綴,但其實trie是一個以空間換時間的算法。其每個字符均可能包含至多字符集大小數目的指針(不包含衛星數據)。

每一個結點的子樹的根節點的組織方式有幾種。1>若是默認包含全部字符集,則查找速度快但浪費空間(特別是靠近樹底部葉子)。2>若是用連接法(如左兒子右兄弟),則節省空間但查找需順序(部分)遍歷鏈表。3>alphabet reduction: 減小字符寬度以減小字母集個數。,4>對字符集使用bitmap,再配合連接法。

2,若是數據存儲在外部存儲器等較慢位置,Trie會較hash速度慢(hash訪問O(1)次外存,Trie訪問O(樹高))。

3,長的浮點數等會讓鏈變得很長。可用bitwise trie改進。

 

bit-wise Trie

相似於普通的Trie,可是字符集爲一個bit位,因此孩子也只有兩個。

可用於地址分配,路由管理等。

雖然是按bit位存儲和判斷,但由於cache-local和可高度並行,因此性能很高。跟紅黑樹比,紅黑樹雖然紙面性能更高,可是由於cache不友好和串行運行多,瓶頸在存儲訪問延遲而不是CPU速度。

 

壓縮Trie

壓縮分支條件:

1,Trie基本不變

2,只是查詢

3,key跟結點的特定數據無關

4,分支很稀疏

若容許添加和刪除,就可能須要分裂和合並結點。此時可能須要對壓縮率和更新(裂,並)頻率進行折中。

 

外存Trie

某些變種如後綴樹適合存儲在外部,另外還有B-trie等。

 

應用場景

(1) 字符串檢索
事先將已知的一些字符串(字典)的有關信息保存到trie樹裏,查找另一些未知字符串是否出現過或者出現頻率。
舉例:
1,給出N 個單詞組成的熟詞表,以及一篇全用小寫英文書寫的文章,請你按最先出現的順序寫出全部不在熟詞表中的生詞。
2,給出一個詞典,其中的單詞爲不良單詞。單詞均爲小寫字母。再給出一段文本,文本的每一行也由小寫字母構成。判斷文本中是否含有任何不良單詞。例如,若rob是不良單詞,那麼文本problem含有不良單詞。

3,1000萬字符串,其中有些是重複的,須要把重複的所有去掉,保留沒有重複的字符串。

 

(2)文本預測、自動完成,see also,拼寫檢查

 

(3)詞頻統計

1,有一個1G大小的一個文件,裏面每一行是一個詞,詞的大小不超過16字節,內存限制大小是1M。返回頻數最高的100個詞。

2,一個文本文件,大約有一萬行,每行一個詞,要求統計出其中最頻繁出現的前10個詞,請給出思想,給出時間複雜度分析。

3,尋找熱門查詢:搜索引擎會經過日誌文件把用戶每次檢索使用的全部檢索串都記錄下來,每一個查詢串的長度爲1-255字節。假設目前有一千萬個記錄,這些查詢串的重複度比較高,雖然總數是1千萬,可是若是去除重複,不超過3百萬個。一個查詢串的重複度越高,說明查詢它的用戶越多,也就越熱門。請你統計最熱門的10個查詢串,要求使用的內存不能超過1G。
(1) 請描述你解決這個問題的思路;
(2) 請給出主要的處理流程,算法,以及算法的複雜度。

==》若無內存限制:Trie + 「k-大/小根堆」(k爲要找到的數目)。

不然,先hash分段再對每個段用hash(另外一個hash函數)統計詞頻,再要麼利用歸併排序的某些特性(如partial_sort),要麼利用某使用外存的方法。參考

  「海量數據處理之歸併、堆排、前K方法的應用:一道面試題」 http://www.dataguru.cn/thread-485388-1-1.html

  「算法面試題之統計詞頻前k大」 http://blog.csdn.net/u011077606/article/details/42640867

   算法導論筆記——第九章 中位數和順序統計量 

 

(4)排序

Trie樹是一棵多叉樹,只要先序遍歷整棵樹,輸出相應的字符串即是按字典序排序的結果。
好比給你N 個互不相同的僅由一個單詞構成的英文名,讓你將它們按字典序從小到大排序輸出。

 

(5)字符串最長公共前綴
Trie樹利用多個字符串的公共前綴來節省存儲空間,當咱們把大量字符串存儲到一棵trie樹上時,咱們能夠快速獲得某些字符串的公共前綴。
舉例:
給出N 個小寫英文字母串,以及Q 個詢問,即詢問某兩個串的最長公共前綴的長度是多少?
解決方案:首先對全部的串創建其對應的字母樹。此時發現,對於兩個串的最長公共前綴的長度即它們所在結點的公共祖先個數,因而,問題就轉化爲了離線(Offline)的最近公共祖先(Least Common Ancestor,簡稱LCA)問題。
而最近公共祖先問題一樣是一個經典問題,能夠用下面幾種方法:
1. 利用並查集(Disjoint Set),能夠採用採用經典的Tarjan 算法;
2. 求出字母樹的歐拉序列(Euler Sequence )後,就能夠轉爲經典的最小值查詢(Range Minimum Query,簡稱RMQ)問題了;

 

(6)字符串搜索的前綴匹配
trie樹經常使用於搜索提示。如當輸入一個網址,能夠自動搜索出可能的選擇。當沒有徹底匹配的搜索結果,能夠返回前綴最類似的可能。
Trie樹檢索的時間複雜度能夠作到n,n是要檢索單詞的長度,
若是使用暴力檢索,須要指數級O(n2)的時間複雜度。

 

(7) 做爲其餘數據結構和算法的輔助結構
如後綴樹,AC自動機等

後綴樹能夠用於全文搜索

 

轉一篇關於幾種Trie速度比較的文章:http://www.hankcs.com/nlp/performance-comparison-of-several-trie-tree.html

Trie樹和其它數據結構的比較 http://www.raychase.net/1783

 

參考:

[1] 維基百科:Trie, https://en.wikipedia.org/wiki/Trie

[2] LeetCode字典樹(Trie)總結, http://www.jianshu.com/p/bbfe4874f66f

[3] 字典樹(Trie樹)的實現及應用, http://www.cnblogs.com/binyue/p/3771040.html#undefined

[4] 6天通吃樹結構—— 第五天 Trie樹, http://www.cnblogs.com/huangxincheng/archive/2012/11/25/2788268.html

 

在Trie樹中主要有3個操做,插入、查找和刪除。通常狀況下Trie樹中不多存在刪除單獨某個結點的狀況,所以只考慮刪除整棵樹。

 

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 #define maxn 26
 7 struct Trie{
 8     int Flag;// 經過該節點單詞的數量,可用來統計前綴 
 9     bool End;// 判斷該節點是不是是單詞的結尾
10     char str[20];//若是該節點是單詞結尾(End=true) 可存放整個單詞 
11     Trie *Next[maxn];
12     Trie(){        //結構體初始化 
13         Flag=1;
14         End=false;
15         memset(Next,0,sizeof(Next));
16     }
17 }*Root;
18 
19 void Insert(char *str) //插入操做 
20 {
21     Trie *p=Root;
22     Trie *q=NULL;
23     int len=strlen(str);
24     for(int i=0;i<len;i++)
25     {
26         int key=str[i]-'a'; //數字的話爲 str[i]-'0' 
27         if(!p->Next[key])
28         {
29             q=new Trie(); //不能找到,說明該key沒有在這條支路,新建節點 
30             p->Next[key]=q;
31             p=p->Next[key];
32         }
33         else
34         {
35             p=p->Next[key];
36             p->Flag++; //能查到,則經過該節點(key)的次數加1 
37         }
38         if(i==len-1)//到了字符串的最後一個  
39         {
40             p->End=true;
41             strcpy(p->str,str);
42         } 
43     }
44 } 
45 
46 int Qurey(char *str) //查詢操做,根據查詢的內容,選int bool void 
47 {
48     int len=strlen(str);
49     Trie *p=Root;
50     for(int i=0;i<len;i++)
51     {
52         int key=str[i]-'a';
53         if(!p->Next[key])
54             return 0;
55         p=p->Next[key]; 
56     }
57     return p->Flag; 
58 } 
59 
60 void Free(Trie* T) //釋放字典樹 
61 {
62     if(T==NULL)
63         return;
64         for(int i=0;i<maxn;i++)
65         {
66             if(T->Next[i])
67                 Free(T->Next[i]); //遞歸的方式 
68         }
69     delete(T);
70 }
71 
72 int main()
73 {
74     Root=new Trie();
75 //    char str[20];
76 //    gets(str);
77 //    Insert(str);
78 //    printf("%d",Qurey(str));
79     Free(Root);
80     return 0;
81 }

也能夠用二維數組來表示字典樹,用結構體超時的話,能夠試試數組

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 #define maxn 26
 7 const int MAXN=2e6+5;
 8 int Trie[MAXN][maxn]; //用一個二維數組來表示樹 
 9 int Count[MAXN];      //記錄頻數 
10 bool End[MAXN];       //結尾標誌 
11 int tot;              //總結點數 
12 
13 void Insert(char *str) // 插入操做 
14 {
15     int Root=0;
16     int len=strlen(str);
17     for(int i=0;i<len;i++)
18     {
19         int key=str[i]-'a';
20         if(!Trie[Root][key])
21         {
22             Trie[Root][key]=++tot;//至關於創建新節點 
23             Root=Trie[Root][key];
24             Count[Root]=1;
25         }
26         else
27         {
28             Root=Trie[Root][key];
29             Count[Root]++;
30         }
31     }
32     End[Root]=true;
33 } 
34 
35 bool Qurey(char *str)
36 {
37     int Root=0;
38     int len=strlen(str);
39     for(int i=0;i<len;i++)
40     {
41         int key=str[i]-'a';
42         if(!Trie[Root][key])
43             return false;
44         Root=Trie[Root][key];
45     }
46     return true;
47 }
48 
49 void Clear()
50 {
51     for(int i=0;i<=tot;i++) //注意是<=tot 
52     {
53         End[i]=false;
54         Count[i]=0;
55         for(int j=0;j<maxn;j++)
56         {
57             Trie[i][j]=0;
58         }
59     }
60     tot=0;
61 }
62 
63 int main()
64 {
65 //    char str[20];
66 //    gets(str);
67 //    Insert(str);
68 //    if(Qurey(str))
69 //        printf("Yes\n");
70 //    Clear();
71     return 0;
72 }

 

 

 

 

例題及思路

統計難題

HDU1251

Problem Description

Ignatius最近遇到一個難題,老師交給他不少單詞(只有小寫字母組成,不會有重複的單詞出現),如今老師要他統計出以某個字符串爲前綴的單詞數量(單詞自己也是本身的前綴). 

Input

輸入數據的第一部分是一張單詞表,每行一個單詞,單詞的長度不超過10,它們表明的是老師交給Ignatius統計的單詞,一個空行表明單詞表的結束.第二部分是一連串的提問,每行一個提問,每一個提問都是一個字符串. 

注意:本題只有一組測試數據,處理到文件結束. 

Output

對於每一個提問,給出以該字符串爲前綴的單詞的數量. 

Sample Input

banana
band
bee
absolute
acm

ba
b
band
abc

Sample Output

2
3
1
0

 

統計出以某個字符串爲前綴的單詞數量,首先構建出trie樹並記錄每一個節點的訪問次數,而後在上面查詢就行了,模板題。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <algorithm>
 5 #define MAXN 26
 6 using namespace std;
 7 
 8 struct Trie 
 9 {
10     Trie *Next[MAXN];
11     int Flag;
12     Trie()
13     {
14         Flag=1;
15         memset(Next,NULL,sizeof(Next));
16     }
17 };
18 
19 struct Trie* Root;
20 
21 void Insert(char* str)
22 {
23     Trie *p,*q;
24     p=Root;
25     int len=strlen(str);
26     for(int i=0;i<len;++i)
27     {
28         int key=str[i]-'a';
29         if(p->Next[key]==NULL)
30         {
31             q=new Trie();
32             p->Next[key]=q;
33             p=p->Next[key];
34         }
35         else 
36         {
37             p=p->Next[key];
38             ++p->Flag;
39         }
40     }
41 }
42 
43 int Qurey(char *str)
44 {
45     int len=strlen(str);
46     Trie* p=Root;
47     for(int i=0;i<len;++i)
48     {
49         int key=str[i]-'a';
50         if(p->Next[key]==NULL)
51             return 0;
52         p=p->Next[key];
53     }
54     return p->Flag;
55     
56 }
57 
58 void Free(Trie* T)
59 {
60     if(T==NULL) return;
61     for(int i=0;i<MAXN;i++)
62     {
63         if(T->Next[i]) Free(T->Next[i]);
64     }
65     delete(T);
66 }
67 
68 int main()
69 {
70     //freopen("sample.txt","r",stdin);
71     char str[15];
72     Root=new Trie();
73     while(*gets(str))   //效果等同於while(gets(str)&&str[0]!=0)
74     {
75         Insert(str);
76     }
77     while(~scanf("%s",str))
78     {
79         printf("%d\n",Qurey(str));
80     }
81     Free(Root);
82     return 0;
83 }
View Code

 

 

 

單詞數

HDU2072

Problem Description

lily的好朋友xiaoou333最近很空,他想了一件沒有什麼意義的事情,就是統計一篇文章裏不一樣單詞的總數。下面你的任務是幫助xiaoou333解決這個問題。

Input

有多組數據,每組一行,每組就是一篇小文章。每篇小文章都是由小寫字母和空格組成,沒有標點符號,遇到#時表示輸入結束。

Output

每組只輸出一個整數,其單獨成行,該整數表明一篇文章裏不一樣單詞的總數。

Sample Input

you are my friend
#

Sample Output

 4

 

統計出現的不一樣單詞的個數,直接把字符所有插入Trie樹中,而後遍歷trie樹,統計全部具備End標記的節點個數就行了。

提示:多樣例輸入的格式是第一種,用字符數組會被卡

           

這裏能夠用 istringstream來快速從字符串中根據空格來提取單詞,istringstream對象能夠綁定一行字符串,而後以空格爲分隔符把該行分隔開來。(要加頭文件sstream)

 

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <sstream> 
 6 #define MAXN 26
 7 using namespace std;
 8 
 9 struct Trie
10 {
11     Trie *Next[MAXN];
12     int flag;
13     int end;
14     Trie()
15     {
16         flag=1;
17         end=0;
18         memset(Next,NULL,sizeof(Next));
19     }
20 }*Root;
21 
22 void Insert(string str)
23 {
24     Trie *p=Root;
25     Trie *q;
26     int len=str.size();
27     for(int i=0;i<len;++i)
28     {
29         int key=str[i]-'a';
30         if(p->Next[key]==NULL)
31         {
32             q=new Trie();
33             p->Next[key]=q;
34             p=p->Next[key];
35         }
36         else 
37         {
38             p=p->Next[key];
39             ++p->flag;
40         }
41         if(i==len-1)
42             p->end=1;
43     }
44 }
45 
46 int visit(Trie* T,int &sum) //遍歷trie樹
47 {
48     if(T==NULL)
49         return 0;
50     if(T->end==1)
51         sum++;
52     for(int i=0;i<MAXN;i++)
53     {
54         visit(T->Next[i],sum);
55     }
56 }
57 
58 void Free(Trie* T)
59 {
60     if(T==NULL) return;
61     for(int i=0;i<MAXN;i++)
62     {
63         if(T->Next[i]) Free(T->Next[i]);
64     }
65     delete(T);
66 }
67 
68 int main()
69 {
70     string str;
71     string tem;  //字符數組被卡,改用string就過了。。。。
72     int sum=0;
73     Root=new Trie();
74     while(getline(cin,str)&&str!="#")
75     {
76         istringstream is(str); //is至關於存單詞的一個容器
77         while(is>>tem)        //將is中的字符串依次賦給string
78         {
79             Insert(tem);
80         }
81         visit(Root,sum);
82         printf("%d\n",sum);
83         Free(Root);
84         Root=new Trie();
85         sum=0;
86     }
87     Free(Root);
88     return 0;
89 }
View Code

 

 

Shortest Prefixes

POJ2001

Description

A prefix of a string is a substring starting at the beginning of the given string. The prefixes of "carbon" are: "c", "ca", "car", "carb", "carbo", and "carbon". Note that the empty string is not considered a prefix in this problem, but every non-empty string is considered to be a prefix of itself. In everyday language, we tend to abbreviate words by prefixes. For example, "carbohydrate" is commonly abbreviated by "carb". In this problem, given a set of words, you will find for each word the shortest prefix that uniquely identifies the word it represents. 

In the sample input below, "carbohydrate" can be abbreviated to "carboh", but it cannot be abbreviated to "carbo" (or anything shorter) because there are other words in the list that begin with "carbo". 

An exact match will override a prefix match. For example, the prefix "car" matches the given word "car" exactly. Therefore, it is understood without ambiguity that "car" is an abbreviation for "car" , not for "carriage" or any of the other words in the list that begins with "car". 

Input

The input contains at least two, but no more than 1000 lines. Each line contains one word consisting of 1 to 20 lower case letters.

Output

The output contains the same number of lines as the input. Each line of the output contains the word from the corresponding line of the input, followed by one blank space, and the shortest prefix that uniquely (without ambiguity) identifies this word.

Sample Input

carbohydrate
cart
carburetor
caramel
caribou
carbonic
cartilage
carbon
carriage
carton
car
carbonate

Sample Output

carbohydrate carboh
cart cart
carburetor carbu
caramel cara
caribou cari
carbonic carboni
cartilage carti
carbon carbon
carriage carr
carton carto
car car
carbonate carbona

求一個能表明這個字符串的最短前綴,也就是隻有這個字符串具備的前綴,不然輸出這個字符串自己

作法很顯然,先構建好Trie樹,而後對每一個單詞進行find,遞歸到直到節點出現次數爲1,表示這個節點只有這一個單詞走過,返回就ok。

這裏能夠用string不斷拼接字符,而後直接返回,減小一些代碼量。

 

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 #define MAXN 26
 7 const int maxn=2e6+5;
 8 int Trie[maxn][MAXN];
 9 int Count[maxn];
10 bool End[maxn];
11 int tot;
12 
13 void Find(char *str)
14 {
15     int len=strlen(str);
16     int Root=0;
17     int flag=1;
18     int i;
19     for(i=0;i<len;i++)
20     {
21         int key=str[i]-'a';
22         Root=Trie[Root][key];
23         printf("%c",str[i]);
24         if(Count[Root]==1)
25         {
26             printf("\n");
27             return;
28         }     
29     }
30     printf("\n");
31     return ;
32 }
33 
34 void Insert(char *str)
35 {
36     int len=strlen(str);
37     int Root=0;
38     for(int i=0;i<len;i++)
39     {
40         int key=str[i]-'a';
41         if(!Trie[Root][key])
42         {
43             Trie[Root][key]=++tot;
44             Count[Trie[Root][key]]=1;
45         }
46         else
47         {
48             Count[Trie[Root][key]]++;
49         }    
50         Root=Trie[Root][key];
51     }
52     End[Root]=true;
53 }
54 
55 void init()
56 {
57     for(int i=0;i<=tot;i++)
58     {
59         End[i]=false;
60         Count[i]=0;
61         for(int j=0;j<MAXN;j++)
62         {
63             Trie[i][j]=0;
64         }
65     }
66     tot=0;
67 }
68 char ss[1005][21];
69 int main()
70 {
71     int num=0;
72     while(scanf("%s",ss[num])!=EOF)
73     {
74         Insert(ss[num++]);
75     }
76     for(int i=0;i<num;i++)
77     {
78         printf("%s ",ss[i]);
79         Find(ss[i]);
80     }
81     init();
82     return 0;
83 }
View Code

 

 

Phone List

POJ3630

Description

Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let's say the phone catalogue listed these numbers:

  • Emergency 911
  • Alice 97 625 999
  • Bob 91 12 54 26

In this case, it's not possible to call Bob, because the central would direct your call to the emergency line as soon as you had dialled the first three digits of Bob's phone number. So this list would not be consistent.

Input

The first line of input gives a single integer, 1 ≤ t ≤ 40, the number of test cases. Each test case starts with n, the number of phone numbers, on a separate line, 1 ≤ n ≤ 10000. Then follows n lines with one unique phone number on each line. A phone number is a sequence of at most ten digits.

Output

For each test case, output "YES" if the list is consistent, or "NO" otherwise.

Sample Input

2
3
911
97625999
91125426
5
113
12340
123440
12345
98346

Sample Output

NO
YES

給出一個字符串集合,問是否全部的字符串都不是其餘字符串的前綴

若是字符串Xn=X1X2....Xn是字符串Ym=Y1Y2....Ym的前綴,有在插入的時候有兩種狀況:Xn在Yn以前插入,Xn在Yn以後插入。
  1)若是Xn在Yn以前插入,那麼在插入Yn的時候必然通過Xn的路徑,此時能夠根據判斷在這條路徑上是否已經有結點被標記已經構成完成的字符串序列來判斷是否存在Yn的前綴;
  2)若是Xn在Yn以後插入,那麼插入完成以後當前指針指向的結點的next數組中的元素一定不全爲NULL或0。
 

以前一直時間超限。。。。把鏈式結構換成了二維數組

而後這個居然wa掉了,

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 #define MAXN 10
 7 const int maxn=2e6+5;
 8 int Trie[maxn][MAXN];
 9 bool End[maxn];
10 int tot;
11 
12 void init()
13 {
14     for(int i=0;i<tot;i++)
15     {
16         End[i]=false;
17         for(int j=0;j<MAXN;j++)
18         {
19             Trie[i][j]=0;
20         }
21     }
22     tot=0;
23 }
24 
25 int main()
26 {
27     int t;
28     scanf("%d",&t);
29     while(t--)
30     {
31         int n;
32         scanf("%d",&n);
33         getchar();
34         int flag=1; 
35         while(n--)
36         {
37             char str[20];
38             gets(str);
39             int len=strlen(str);
40             int Root=0;
41             for(int i=0;i<len;i++)
42             {
43                 int key=str[i]-'0';
44                 if(!Trie[Root][key])
45                     Trie[Root][key]=++tot;
46                 else if(End[Trie[Root][key]]==true)
47                 {
48                     flag=0;
49                 }
50                 Root=Trie[Root][key];
51                 if(i==len-1)
52                     End[Root]=true;
53             }
54             for(int i=0;i<MAXN;i++)
55             {
56                 if(Trie[Root][i]!=0)
57                 {
58                     flag=0;
59                     break;
60                 }
61             }
62         }
63         if(flag)
64             printf("YES\n");
65         else 
66             printf("NO\n");
67         init();
68     }
69     return 0;
70 }
View Code

後來終於過了,原來是init函數的問題,把i < tot改成了i <= tot就AC了,卡了我好長時間

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 #define MAXN 10
 7 const int maxn=2e6+5;
 8 int Trie[maxn][MAXN];
 9 bool End[maxn];
10 int tot;
11 
12 void init()
13 {
14     for(int i=0;i<=tot;i++)   //這裏把<改成了<=就AC了
15     {
16         End[i]=false;
17         for(int j=0;j<MAXN;j++)
18         {
19             Trie[i][j]=0;
20         }
21     }
22     tot=0;
23 }
24 
25 int main()
26 {
27     //freopen("sampletem.txt","r",stdin);
28     int t;
29     scanf("%d",&t);
30     while(t--)
31     {
32         int n;
33         scanf("%d",&n);
34         getchar();
35         int flag=1; 
36         while(n--)
37         {
38             char str[20];
39             gets(str);
40             int len=strlen(str);
41             int Root=0;
42             for(int i=0;i<len;i++)
43             {
44                 int key=str[i]-'0';
45                 if(!Trie[Root][key])
46                     Trie[Root][key]=++tot;
47                 else if(End[Trie[Root][key]]==true)
48                 {
49                     flag=0;
50                 }
51                 Root=Trie[Root][key];
52                 if(i==len-1)
53                     End[Root]=true;
54             }
55             for(int i=0;i<MAXN;i++)
56             {
57                 if(Trie[Root][i]!=0)
58                 {
59                     flag=0;
60                     break;
61                 }
62             }
63         }
64         if(flag)
65             printf("YES\n");
66         else 
67             printf("NO\n");
68         init();
69     }
70     return 0;
71 }
View Code

 

 

T9

POJ1451

Description

Background 

A while ago it was quite cumbersome to create a message for the Short Message Service (SMS) on a mobile phone. This was because you only have nine keys and the alphabet has more than nine letters, so most characters could only be entered by pressing one key several times. For example, if you wanted to type "hello" you had to press key 4 twice, key 3 twice, key 5 three times, again key 5 three times, and finally key 6 three times. This procedure is very tedious and keeps many people from using the Short Message Service. 

This led manufacturers of mobile phones to try and find an easier way to enter text on a mobile phone. The solution they developed is called T9 text input. The "9" in the name means that you can enter almost arbitrary words with just nine keys and without pressing them more than once per character. The idea of the solution is that you simply start typing the keys without repetition, and the software uses a built-in dictionary to look for the "most probable" word matching the input. For example, to enter "hello" you simply press keys 4, 3, 5, 5, and 6 once. Of course, this could also be the input for the word "gdjjm", but since this is no sensible English word, it can safely be ignored. By ruling out all other "improbable" solutions and only taking proper English words into account, this method can speed up writing of short messages considerably. Of course, if the word is not in the dictionary (like a name) then it has to be typed in manually using key repetition again. 
      
            Figure 8: The Number-keys of a mobile phone.

 More precisely, with every character typed, the phone will show the most probable combination of characters it has found up to that point. Let us assume that the phone knows about the words "idea" and "hello", with "idea" occurring more often. Pressing the keys 4, 3, 5, 5, and 6, one after the other, the phone offers you "i", "id", then switches to "hel", "hell", and finally shows "hello". 

Problem 

Write an implementation of the T9 text input which offers the most probable character combination after every keystroke. The probability of a character combination is defined to be the sum of the probabilities of all words in the dictionary that begin with this character combination. For example, if the dictionary contains three words "hell", "hello", and "hellfire", the probability of the character combination "hell" is the sum of the probabilities of these words. If some combinations have the same probability, your program is to select the first one in alphabetic order. The user should also be able to type the beginning of words. For example, if the word "hello" is in the dictionary, the user can also enter the word "he" by pressing the keys 4 and 3 even if this word is not listed in the dictionary.

Input

The first line contains the number of scenarios. 
Each scenario begins with a line containing the number w of distinct words in the dictionary (0<=w<=1000). These words are given in the next w lines. (They are not guaranteed in ascending alphabetic order, although it's a dictionary.) Every line starts with the word which is a sequence of lowercase letters from the alphabet without whitespace, followed by a space and an integer p, 1<=p<=100, representing the probability of that word. No word will contain more than 100 letters. 
Following the dictionary, there is a line containing a single integer m. Next follow m lines, each consisting of a sequence of at most 100 decimal digits 2-9, followed by a single 1 meaning "next word". 

Output

The output for each scenario begins with a line containing "Scenario #i:", where i is the number of the scenario starting at 1. 
For every number sequence s of the scenario, print one line for every keystroke stored in s, except for the 1 at the end. In this line, print the most probable word prefix defined by the probabilities in the dictionary and the T9 selection rules explained above. Whenever none of the words in the dictionary match the given number sequence, print "MANUALLY" instead of a prefix. 
Terminate the output for every number sequence with a blank line, and print an additional blank line at the end of every scenario. 

Sample Input

2
5
hell 3
hello 4
idea 8
next 8
super 3
2
435561
43321
7
another 5
contest 6
follow 3
give 13
integer 6
new 14
program 4
5
77647261
6391
4681
26684371
77771

Sample Output

Scenario #1:
i
id
hel
hell
hello

i
id
ide
idea


Scenario #2:
p
pr
pro
prog
progr
progra
program

n
ne
new

g
in
int

c
co
con
cont
anoth
anothe
another

p
pr
MANUALLY
MANUALLY

 

Hat’s Words

HDU1247

Problem Description

A hat’s word is a word in the dictionary that is the concatenation of exactly two other words in the dictionary.
You are to find all the hat’s words in a dictionary.

Input

Standard input consists of a number of lowercase words, one per line, in alphabetical order. There will be no more than 50,000 words.
Only one case.

Output

Your output should contain all the hat’s words, one per line, in alphabetical order.

Sample Input

a
ahat
hat
hatword
hziee
word

Sample Output

ahat
hatword

 

給出n個按字典序排列的單詞,問其中的全部能由另外兩個單詞組成的單詞並按字典序輸出

(推薦)思路1:先建好字典樹,而後枚舉一個單詞將其拆分紅兩個單詞並查詢字典樹中是否有這兩個單詞;

思路2:先把全部的單詞構形成一顆trie圖,而後對全部的單詞進行枚舉,在trie圖上面判斷一個單詞是否由其它兩個單詞構成,具備的作法是先沿着路徑一直走,若是走到某個節點,該節點爲一個單詞的結尾,那麼再對剩餘的單詞再從trie圖的根開始遍歷,看是否能和一個單詞匹配,若匹配成功則該單詞知足要求,不然繼續進行匹配...

思路3:能夠建兩顆Trie樹,而後分別正序倒序插入每一個單詞,對每一個單詞查詢的時候,分別正序倒序查詢,對出現過單詞的前綴下標進行標記,對每一個出現過單詞的後綴進行標記,最後掃描標記數組,若是某個位置前綴後綴均被標記過,則表示能夠拆成單詞表中的兩個其餘單詞。

 

沒有想到該怎樣枚舉,只想選一個單詞另外兩個怎麼選,該弄多少個循環呀,看了別人的方法才知道將這個單詞拆分紅兩個單詞;還了解了strncpy,一些字符函數能用則用,原本就是爲了方便!

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <string>
  4 #include <string.h>
  5 #include <stdlib.h>
  6 #include <algorithm>
  7 using namespace std;
  8 #define MAXN 26
  9 
 10 char word[50005][50];
 11 char ss1[50],ss2[50];
 12 int num;
 13 
 14 struct Trie{
 15     int Flag; 
 16     Trie *Next[MAXN];
 17     Trie()
 18     {
 19         Flag=0;
 20         memset(Next,NULL,sizeof(Next));
 21     }
 22 }*Root;
 23 
 24 void Insert(char *str)
 25 {
 26     Trie *p=Root;
 27     Trie *q=NULL;
 28     int len=strlen(str);
 29     for(int i=0;i<len;i++)
 30     {
 31         int key=str[i]-'a';
 32         if(!p->Next[key])
 33         {
 34             q=new Trie();
 35             p->Next[key]=q;
 36         }
 37         p=p->Next[key];
 38         if(i==len-1)
 39         p->Flag=1;
 40     }
 41     return;
 42 } 
 43 
 44 int Qurey(char *str)
 45 {
 46     Trie *p=Root;
 47     int len=strlen(str);
 48     int flag=0;
 49     for(int i=0;i<len;i++)
 50     {
 51         int key=str[i]-'a';
 52         if(!p->Next[key])
 53         {
 54             return 0;
 55         }
 56         p=p->Next[key];
 57     }
 58     return p->Flag;
 59 }
 60 
 61 void Find(char *str)
 62 {
 63     int len=strlen(str);
 64     for(int m=1;m<len;m++)
 65     {
 66         //這裏用strncmp 
 67         strncpy(ss1,str,m);
 68         ss1[m]=0;
 69         strncpy(ss2,str+m,len-m+1);
 70         ss2[len-m+1]=0;
 71 //      不用strncmp的話 
 72 //        int j=0;
 73 //        for(int i=0;i<m;i++)
 74 //        {
 75 //            ss1[j++]=str[i];
 76 //        }
 77 //        ss1[j]=0;
 78 //        j=0;
 79 //        for(int i=m;i<len;i++)
 80 //        {
 81 //            ss2[j++]=str[i];
 82 //        }
 83 //        ss2[j]=0;
 84         //printf("ss1=%s ss2=%s\n",ss1,ss2);
 85         if(Qurey(ss1)&&Qurey(ss2))
 86         {
 87             puts(str);
 88             break;   //不帶break;就wa掉了,無語 
 89         }
 90     }
 91 }
 92 
 93 void Free(Trie *T)
 94 {
 95     if(T==NULL) return;
 96     for(int i=0;i<MAXN;i++)
 97     {
 98         if(T->Next[i]) Free(T->Next[i]);
 99     }
100     delete(T);
101 }
102 
103 int main()
104 {
105     freopen("sampletem.txt","r",stdin);
106     char str[50];
107     Root=new Trie();
108     while(~scanf("%s",str))
109     {
110         strcpy(word[num++],str);
111         Insert(str);
112     }
113     for(int i=0;i<num;i++)
114     {
115         Find(word[i]);
116     }
117     Free(Root);
118     return 0;
119 }
View Code

 

 

Anagram Groups

 POJ2408

World-renowned Prof. A. N. Agram's current research deals with large anagram groups. He has just found a new application for his theory on the distribution of characters in English language texts. Given such a text, you are to find the largest anagram groups. 
A text is a sequence of words. A word w is an anagram of a word v if and only if there is some permutation p of character positions that takes w to v. Then, w and v are in the same anagram group. The size of an anagram group is the number of words in that group. Find the 5 largest anagram groups.

Input

The input contains words composed of lowercase alphabetic characters, separated by whitespace(or new line). It is terminated by EOF. You can assume there will be no more than 30000 words.

Output

Output the 5 largest anagram groups. If there are less than 5 groups, output them all. Sort the groups by decreasing size. Break ties lexicographically by the lexicographical smallest element. For each group output, print its size and its member words. Sort the member words lexicographically and print equal words only once.

Sample Input

undisplayed
trace
tea
singleton
eta
eat
displayed
crate
cater
carte
caret
beta
beat
bate
ate
abet

Sample Output

Group of size 5: caret carte cater crate trace .
Group of size 4: abet bate beat beta .
Group of size 4: ate eat eta tea .
Group of size 1: displayed .
Group of size 1: singleton .

把能夠經過從新排列變成相同單詞的單詞放入一個集合,最後按照集合元素由多到少輸出前五個集合,若是集合元素相同,按照字典序由小到大輸出

把每個字符串,升序排序,能夠獲得一個字符串,若是兩個字符串的字典序最小的字符串相同,就屬於一個組, 因此用字典樹記錄這個最小字典序的字符串,而後映射下標到group結構體(存各類字符串,及個數,因爲字符串輸出要去重,因此用set,這樣函數傳參數要引用傳遞,不然很慢),最後按照個數排序。

無論是用鏈式仍是順序,一直超時,感受是算法太耗時

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <string>
  4 #include <string.h>
  5 #include <set>
  6 #include <stdlib.h>
  7 #include <algorithm>
  8 using namespace std;
  9 #define MAXN 26
 10 const int maxn=1e6+5;
 11 int Trie[maxn][MAXN];
 12 int tot;
 13 //bool Flag[maxn];
 14 int To[maxn];
 15 int num;
 16 
 17 struct Group{
 18     int size;
 19     set<string> st;
 20 }group[50005];
 21 
 22 bool cmp(const Group &a,const Group &b)
 23 {
 24     if(a.size!=b.size)
 25         return a.size>b.size;
 26     else 
 27         return *(a.st.begin()) < *(b.st.begin());
 28 }
 29 
 30 void Insert(char *str)
 31 {
 32     int Root=0;
 33     string ss="";
 34     ss=str;
 35     int len=strlen(str);
 36 //    for(int i=0;i<len;i++)
 37 //    {
 38 //        ss+=str[i];
 39 //    }
 40     sort(str,str+len);
 41     //puts(str);
 42 //    int t=0;
 43     for(int i=0;i<len;i++)
 44     {
 45         int key=str[i]-'a';
 46         if(!Trie[Root][key])
 47         {
 48         //    t=1;
 49             Trie[Root][key]=++tot;
 50         }
 51         Root=Trie[Root][key];
 52 //        if(t&&i==len-1)
 53 //        {
 54 //            Flag[Root]=true;
 55 //            To[Root]=num;
 56 //            group[num].size++;
 57 //            group[num].st.insert(ss);
 58 //            num++;
 59 //            //printf("%d\n",num);
 60 //        }
 61     }
 62     if(!To[Root])
 63     {
 64         To[Root]=num++;
 65     }
 66     group[To[Root]].size++;
 67     group[To[Root]].st.insert(ss);
 68 //    if(!t&&Flag[Root]==true)
 69 //    {
 70 //        group[To[Root]].size++;
 71 //        group[To[Root]].st.insert(ss);
 72 //    }
 73     return;
 74 } 
 75 
 76 //void init()
 77 //{
 78 //    for(int i=0;i<=tot;i++)
 79 //    {
 80 //        To[i]=0;
 81 //        for(int j=0;j<MAXN;j++)
 82 //        {
 83 //            Trie[i][j]=0;
 84 //        }
 85 //    }
 86 //    tot=0;
 87 //}
 88 
 89 int main()
 90 {
 91     //freopen("sampletem.txt","r",stdin);
 92     char str[50];
 93     while(gets(str))
 94     {
 95         Insert(str);
 96     }
 97     sort(group,group+num,cmp);
 98     int n;
 99     if(num>=5)
100         n=5;
101     else    n=num;
102     for(int i=0;i<n;i++)
103     {
104         printf("Group of size %d: ",group[i].size);
105         set<string>::iterator it;
106         for(it=group[i].st.begin();it!=group[i].st.end();it++)
107         {
108             printf("%s ",(*it).c_str());
109         }
110         printf(".\n");
111     }
112     //init();
113     return 0;
114 }
View Code

 

 數組的方法,換個G++編譯就過了。。。。

 

結構體的換了語言也是超時 

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <string>
  4 #include <string.h>
  5 #include <set>
  6 #include <stdlib.h>
  7 #include <algorithm>
  8 using namespace std;
  9 #define MAXN 26
 10 int num;
 11 struct Group{
 12     int size;
 13     set<string> st;
 14 }group[50005];
 15 
 16 struct Trie{ 
 17     Trie *Next[MAXN];
 18     int To;
 19     Trie()
 20     {
 21         To=0;
 22         memset(Next,NULL,sizeof(Next));
 23     }
 24 }*Root;
 25 
 26 bool cmp(Group a,Group b)
 27 {
 28     if(a.size!=b.size)
 29         return a.size>b.size;
 30     else 
 31         return *(a.st.begin()) < *(b.st.begin());
 32 }
 33 
 34 void Insert(char *str)
 35 {
 36     Trie *p=Root;
 37     Trie *q=NULL;
 38     string ss="";
 39     int len=strlen(str);
 40     for(int i=0;i<len;i++)
 41     {
 42         ss+=str[i];
 43     }
 44     sort(str,str+len);
 45     //puts(str);
 46     for(int i=0;i<len;i++)
 47     {
 48         int key=str[i]-'a';
 49         if(!p->Next[key])
 50         {
 51             q=new Trie();
 52             p->Next[key]=q;
 53         }
 54         p=p->Next[key];
 55     }
 56     if(p->To==0)
 57     {
 58         p->To=num++;
 59     }
 60     group[p->To].size++;
 61     group[p->To].st.insert(ss);
 62     return;
 63 } 
 64 
 65 void Free(Trie *T)
 66 {
 67     if(T==NULL) return;
 68     for(int i=0;i<MAXN;i++)
 69     {
 70         if(T->Next[i]) Free(T->Next[i]);
 71     }
 72     delete(T);
 73 }
 74 
 75 int main()
 76 {
 77     freopen("sampletem.txt","r",stdin);
 78     char str[50];
 79     Root=new Trie();
 80     while(gets(str))
 81     {
 82         Insert(str);
 83     }
 84     sort(group,group+num,cmp);
 85     int n;
 86     if(num>=5)
 87         n=5;
 88     else    n=num;
 89     for(int i=0;i<n;i++)
 90     {
 91         printf("Group of size %d: ",group[i].size);
 92         set<string>::iterator it;
 93         for(it=group[i].st.begin();it!=group[i].st.end();it++)
 94         {
 95             printf("%s ",(*it).c_str());
 96         }
 97         printf(".\n");
 98     }
 99     Free(Root);
100     return 0;
101 }
View Code

 

過不了啊~~~~~,超時什麼鬼,不想再用tire樹了。。

同窗用map的作法

 1 //MADE BY Y_is_sunshine;
 2 //#include <bits/stdc++.h>
 3 //#include <memory.h>
 4 #include <algorithm>
 5 #include <iostream>
 6 #include <cstdlib>
 7 #include <cstring>
 8 #include <sstream>
 9 #include <cstdio>
10 #include <vector>
11 #include <string>
12 #include <cmath>
13 #include <queue>
14 #include <stack>
15 #include <map>
16 #include <set>
17 
18 #define MAXN 26
19 
20 using namespace std;
21 
22 int main()
23 {
24     //freopen("data.txt", "r", stdin);
25 
26     map<string, int> mp1;
27     map<string, set<string>> mp2;
28 
29     string s1;
30     while (cin >> s1) {
31         string s2;
32         s2 = s1;
33         sort(s2.begin(), s2.end());
34         mp1[s2]++;
35         mp2[s2].insert(s1);
36     }
37 
38     int T = 5;
39     while (T--) {
40         int maxn = -1;
41         string s1, s2;
42         for (map<string, int>::iterator it1 = mp1.begin(); it1 != mp1.end(); it1++) {
43             if (it1->second > maxn) {
44                 maxn = it1->second;
45                 s2 = it1->first;
46             }
47             else if (it1->second == maxn) {
48                 string s3, s4;
49                 s3 = *mp2[s2].begin();
50                 s4 = *mp2[it1->first].begin();
51                 if (s3 > s4) {
52                     maxn = it1->second;
53                     s2 = it1->first;
54                 }
55             }
56         }
57         if (mp1[s2]) {
58             cout << "Group of size " << mp1[s2] << ": ";
59             mp1[s2] = 0;
60             for (set<string>::iterator it1 = mp2[s2].begin(); it1 != mp2[s2].end(); it1++)
61                 cout << *it1 << ' ';
62             cout << "." << endl;
63         }
64     }
65 
66     //freopen("CON", "r", stdin);
67     //system("pause");
68     return 0;
69 }
View Code

 

 

What Are You Talking About

HDU1075

Problem Description

Ignatius is so lucky that he met a Martian yesterday. But he didn't know the language the Martians use. The Martian gives him a history book of Mars and a dictionary when it leaves. Now Ignatius want to translate the history book into English. Can you help him?

Input

The problem has only one test case, the test case consists of two parts, the dictionary part and the book part. The dictionary part starts with a single line contains a string "START", this string should be ignored, then some lines follow, each line contains two strings, the first one is a word in English, the second one is the corresponding word in Martian's language. A line with a single string "END" indicates the end of the directory part, and this string should be ignored. The book part starts with a single line contains a string "START", this string should be ignored, then an article written in Martian's language. You should translate the article into English with the dictionary. If you find the word in the dictionary you should translate it and write the new word into your translation, if you can't find the word in the dictionary you do not have to translate it, and just copy the old word to your translation. Space(' '), tab('\t'), enter('\n') and all the punctuation should not be translated. A line with a single string "END" indicates the end of the book part, and that's also the end of the input. All the words are in the lowercase, and each word will contain at most 10 characters, and each line will contain at most 3000 characters.

Output

In this problem, you have to output the translation of the history book.
 

Sample Input

START
from fiwo
hello difh
mars riwosf
earth fnnvk
like fiiwj
END
START
difh, i'm fiwo riwosf.
i fiiwj fnnvk!
END

Sample Output

hello, i'm from mars.
i like earth!

Hint

Huge input, scanf is recommended.

 

本題的題意是給你火星文與地球文的映射方式,而後給你一個火星文組成的文本,若某單詞在映射文本中出現過,則輸出映射以後的文本。不然輸出原文本

字典樹,經典題,字典翻譯
  WA了1次,後來發現是我把要翻譯的單詞搞錯了,若是一個能夠翻譯的較長的單詞包含着另外一個能夠翻譯的較短的單詞,這樣遍歷句子的時候就會先碰到較短的單詞,WA的程序會先把這個短單詞翻譯出來,但實際上這是不對的,應該翻譯整個較長的單詞,而不是遇到什麼就翻譯什麼。
  個人程序運行時間是281MS,用鏈表作的,用數組應該會快些。
   題意
  只有一組測試數據,分紅兩部分。 第一部分是字典,給你若干個單詞以及對應的翻譯,以START開始,END結束; 第二部分是翻譯部分,給你若干句子,要求你根據上面給出的字典,將火星文翻譯成英文,以START開始,END結束。這裏翻譯的時候,要 注意只有字典中有對應翻譯的單詞才翻譯,字典中沒有對應翻譯的單詞以及標點符號空格原樣輸出。
   思路
  將字典中的火星文單詞,也就是右邊的單詞構形成一棵字典樹。在單詞結束的節點中存儲其對應的英文翻譯。輸入的時候讀取整行,而後遍歷每個字符,將全部字母連續的記錄到一個字符數組中,直到遇到一個非英文字母的字符爲止,這個時候從字典樹中查找這個單詞有沒有對應的英文翻譯,若是有,輸出這個翻譯,若是沒有,輸出原來的單詞。
   注意
  1.輸入方法,使用的scanf+gets。
  2.不要搞錯要翻譯的單詞,遇到一個非字母的字符算一個單詞。
  3.儘可能不要使用cin,cout,容易超時
  1 #include <cstdio>
  2 #include <iostream>
  3 #include <string>
  4 #include <string.h>
  5 #include <stdlib.h>
  6 #include <algorithm>
  7 using namespace std;
  8 #define MAXN 26
  9 string fin="";
 10 
 11 struct Trie{
 12     int Flag; 
 13     Trie *Next[MAXN];
 14     string chc;
 15     Trie()
 16     {
 17         Flag=0;
 18         memset(Next,NULL,sizeof(Next));
 19     }
 20 }*Root;
 21 
 22 void Insert(string str,string ss)
 23 {
 24     Trie *p=Root;
 25     Trie *q=NULL;
 26     int len=str.size();
 27     for(int i=0;i<len;i++)
 28     {
 29         int key=str[i]-'a';
 30         if(!p->Next[key])
 31         {
 32             q=new Trie();
 33             p->Next[key]=q;
 34         }
 35         p=p->Next[key];
 36         if(i==len-1)
 37         p->Flag=1;
 38         p->chc=ss;
 39     }
 40     return;
 41 } 
 42 
 43 void Qurey(string str)
 44 {
 45     Trie *p=Root;
 46     int len=str.size();
 47     int flag=0;
 48     for(int i=0;i<len;i++)
 49     {
 50         int key=str[i]-'a';
 51         if(!p->Next[key])
 52         {
 53             flag=1;
 54             break;
 55         }
 56         else
 57             p=p->Next[key];
 58         if(i==len-1&&p->Flag==1)
 59             fin+=p->chc; 
 60     }
 61     if(flag||p->Flag!=1)
 62         fin+=str;
 63     return;
 64 }
 65 
 66 int main()
 67 {
 68     //freopen("sampletem.txt","r",stdin);
 69     string a,b;
 70     Root=new Trie();
 71     cin>>a;
 72     while(cin>>a)
 73     {
 74         if(a[0]=='E')
 75             break;
 76         cin>>b;
 77         Insert(b,a);
 78     }
 79     cin>>a;
 80     getchar();
 81     char c;
 82     string tem="";
 83     while(c=getchar())
 84     {
 85         if(c=='E')
 86         {
 87             c=getchar();
 88             c=getchar();
 89             break;
 90         }
 91         else if(c>='a'&&c<='z')
 92         {
 93             tem+=c;
 94         }
 95         else 
 96         {
 97             if(tem!="")
 98                 Qurey(tem);
 99             fin+=c;
100             tem="";
101         }
102     }
103     cout<<fin;
104     return 0;
105 }
View Code
相關文章
相關標籤/搜索