標籤:des style blog http color os io 檔案
統計難題
Problem DescriptionIgnatius近期遇到一個難題,老師交給他非常多單詞(僅僅有小寫字母組成,不會有反覆的單詞出現),如今老師要他統計出以某個字串為首碼的單詞數量(單詞本身也是自己的首碼).
Input輸入資料的第一部分是一張單詞表,每行一個單詞,單詞的長度不超過10,它們代表的是老師交給Ignatius統計的單詞,一個空行代表單詞表的結束.第二部分是一連串的提問,每行一個提問,每一個提問都是一個字串.
注意:本題僅僅有一組測試資料,處理到檔案結束.
Output對於每一個提問,給出以該字串為首碼的單詞的數量.
Sample Input
bananabandbeeabsoluteacmbabbandabc
Sample Output
2310
AuthorIgnatius.L
解題思路:
這是第一次做字典樹的題目。字典樹百度百科:又稱單詞尋找樹,Trie樹,是一種樹形結構,是一種雜湊樹的變種。典型應用是用於統計,排序和儲存大量的字串(但不僅限於字串),所以常常被搜尋引擎系統用於文本詞頻統計。它的長處是:利用字串的公用首碼來降低查詢時間,最大限度地降低無謂的字串比較,查詢效率比雜湊表高。
學習了字典樹之後,認為它非常明顯的就是用空間來換時間,空間複雜度特別大,比方字典數單單存26個小寫字母,那麼每一個節點的孩子節點都有26個孩子節點,字典樹中的每一層都保留著不同單詞的同樣字母。
為了好說明,如果,全部的單詞僅僅包含a,b,c,d四個字母,那麼樹是這樣建立的。
題目是要求統計出以某個字串為首碼的單詞數量,字典樹入門題。
代碼:
#include <iostream>#include <string.h>#include <stdio.h>#include <malloc.h>using namespace std;char str[12];const int maxn=26;//孩子節點的最大個數,假設是僅僅有26個字母,就用26就能夠了。struct Trie//樹的結構體{ int cnt;//儲存某個字母出現的次數 Trie *next[maxn];//每個節點相應著多少個孩子,假設僅僅有26個字母,就用26就能夠了};Trie root;/*void init(Trie t){ for(int i=0;i<26;i++) t.next[i]=NULL;}*///不須要單獨對根節點初始化void CreateTrie(char *str){ int len=strlen(str); Trie *p=&root,*q; for(int i=0;i<len;i++) { int id=str[i]-'a'; if(p->next[id]==NULL)//第一次遇到 { q=(Trie*)malloc(sizeof(Trie)); q->cnt=1;//此處一開始寫錯,寫成了q->cnt++; for(int i=0;i<maxn;i++) q->next[i]=NULL;//初始化非空節點的孩子節點 p->next[id]=q;//在樹中填上 p=p->next[id];//此時的P是不為空白的節點 } else { p->next[id]->cnt++;//不是第一次遇到,個數++ p=p->next[id]; } }}int find(char *str){ int len=strlen(str); Trie *p=&root; for(int i=0;i<len;i++) { int id=str[i]-'a'; p=p->next[id];//一直向下走。 if(p==NULL)//找不到該單詞,一開始此處寫錯了,寫成了p->next[id]==NULL return 0; } return p->cnt;}int main(){ while(gets(str)&&str[0]!='\0') { CreateTrie(str); } while(scanf("%s",str)!=EOF) { printf("%d\n",find(str)); } return 0;}