hdu 1251:統計難題(字典樹,經典題)

統計難題

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others)
Total Submission(s): 16905    Accepted Submission(s): 7273


php

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

 

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

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

 

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

 

Sample Input
banana
band
bee
absolute
acm
 
ba
b
band
abc
 

 

Sample Output
2
3
1
0
 

 

Author
Ignatius.L
 

 

Recommend
Ignatius.L   |   We have carefully selected several similar problems for you:   1075  1247  1671  1298  1800 

 
  字典樹,經典題
  今早看了看資料,晚上就會作題了,真的不難,不明白本身爲何放了這麼久纔看。字典樹仍是很簡單的。
  我用了2種作法給你們參考,一種是用鏈表存儲,一種是用數組存儲。
  思路
    字典樹的經典應用,給你多個單詞,構建字典樹,而後給你一個字符串,求以這個字符串爲前綴的單詞的數量。
  注意
    注意如何判斷空行,我用了2種方法。
    一、用strlen()計算字符串的長度,若是長度爲0,說明爲空行,退出輸入循環。見代碼一
    二、用gets()讀入。讀入的回車符會自動轉換爲NULL。因此循環讀入,每次檢測讀入進來的字符串的第一個字符是否爲NULL便可。見代碼二。
  代碼一(鏈表)
 1 #include <iostream>
 2 #include <string.h>
 3 using namespace std;  4 
 5 struct Trie{    //字典樹定義
 6     Trie* next[26];  7     int num;    //以當前字符串爲前綴的單詞的數量
 8     Trie()    //構造函數
 9  { 10         int i; 11         for(i=0;i<26;i++){ 12             next[i] = NULL; 13  } 14         num=0; 15  } 16 }; 17 Trie root; 18 void Insert(char word[])    //將字符串word插入到字典樹中
19 { 20     Trie *p = &root; 21     int i; 22     for(i=0;word[i];i++){    //遍歷word的每個字符
23         if(p->next[word[i]-'a']==NULL)    //若是該字符沒有對應的節點
24             p->next[word[i]-'a'] = new Trie;    //建立一個
25         p = p->next[word[i]-'a']; 26         p->num++; 27  } 28 } 29 int Find(char word[])    //返回以字符串word爲前綴的單詞的數量
30 { 31     Trie *p = &root; 32     int i; 33     for(i=0;word[i];i++){    //在字典樹找到該單詞的結尾位置
34         if(p->next[word[i]-'a']==NULL) 35             return 0; 36         p = p->next[word[i]-'a']; 37  } 38     return p->num; 39 } 40 
41 int main() 42 { 43     char word[11]; 44     while(cin.getline(word,12)){    //輸入單詞
45         if(strlen(word)==0 || word[0]==' ')    //若是讀入字符串的長度爲0或者是空格,說明讀入的是空行
46             break; 47  Insert(word); 48  } 49     while(scanf("%s",word)!=EOF){ 50         printf("%d\n",Find(word));    //返回word爲前綴的單詞的數量
51  } 52     return 0; 53 }

   代碼二(數組)ios

 1 #include <iostream>
 2 #include <stdio.h>
 3 using namespace std;  4 
 5 int trie[1000010][26];    //數組形式定義字典樹,值存儲的是下一個字符的位置
 6 int num[1000010]={0};    //附加值,以某一字符串爲前綴的單詞的數量
 7 int pos = 1;  8 
 9 void Insert(char word[])    //在字典樹中插入某個單詞
10 { 11     int i; 12     int c = 0; 13     for(i=0;word[i];i++){ 14         int n = word[i]-'a'; 15         if(trie[c][n]==0)    //若是對應字符尚未值
16             trie[c][n] = pos++; 17         c = trie[c][n]; 18         num[c]++; 19  } 20 } 21 int Find(char word[])    //返回以某個字符串爲前綴的單詞的數量
22 { 23     int i; 24     int c = 0; 25     for(i=0;word[i];i++){ 26         int n = word[i]-'a'; 27         if(trie[c][n]==0) 28             return 0; 29         c = trie[c][n]; 30  } 31     return num[c]; 32 } 33 
34 int main() 35 { 36     char word[11]; 37     while(gets(word)){ 38         if(word[0]==NULL)    //空行。gets讀入的回車符會自動轉換爲NULL。
39             break; 40  Insert(word); 41  } 42     while(gets(word)) 43         printf("%d\n",Find(word)); 44     return 0; 45 }

SUM數組

  如下是2種作法的效率對比函數

  第二行的是第一種作法,第一行的是第二種作法,很明顯,數組作法無論是在時間,空間,代碼量上都要優於鏈表作法。測試

  可是數組的不太好理解,如何取捨看各位看官的意思吧。spa

 

Freecode : www.cnblogs.com/yym2013code

相關文章
相關標籤/搜索