1. 程式人生 > >[ACM] hdu 1251 統計難題 (字典樹)

[ACM] hdu 1251 統計難題 (字典樹)

第一次 stdio.h scrip null 明顯 output 代碼 ane 處理

統計難題



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


解題思路:

這是第一次做字典樹的題目。字典樹百度百科:又稱單詞查找樹,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; }




[ACM] hdu 1251 統計難題 (字典樹)