1337:【例3-2】单词查找树
時間限制: 1000 ms 內存限制: 65536 KB
 提交數: 1732 通過數: 910
【題目描述】
在進行文法分析的時候,通常需要檢測一個單詞是否在我們的單詞列表里。為了提高查找和定位的速度,通常都畫出與單詞列表所對應的單詞查找樹,其特點如下:
1.根結點不包含字母,除根結點外每一個結點都僅包含一個大寫英文字母;
2.從根結點到某一結點,路徑上經過的字母依次連起來所構成的字母序列,稱為該結點對應的單詞。單詞列表中的每個單詞,都是該單詞查找樹某個結點所對應的單詞;
3.在滿足上述條件下,該單詞查找樹的結點數最少。
4.例如圖3-2左邊的單詞列表就對應于右邊的單詞查找樹。注意,對一個確定的單詞列表,請統計對應的單詞查找樹的結點數(包含根結點)。
【輸入】
為一個單詞列表,每一行僅包含一個單詞和一個換行/回車符。每個單詞僅由大寫的英文字母組成,長度不超過63個字母 。文件總長度不超過32K,至少有一行數據。
【輸出】
僅包含一個整數,該整數為單詞列表對應的單詞查找樹的結點數。
【輸入樣例】
A
 AN
 ASP
 AS
 ASC
 ASCII
 BAS
 BASIC
【輸出樣例】
13
【來源】
No
算法分析
首先要對建樹的過程有一個了解。
對于當前被處理的單詞和當前樹:在根節點的子結點中找單詞的第一位字母,若存在,則進位在該節點的子結點中尋找第二位…
如此下去直到單詞結束,即不需要在該樹中添加節點;
或單詞的第n位不能被找到,即將單詞的第n位及其后的字母依次加入單詞查找樹中去。
但是,本題只是問節點總數,且有32K文件,所以應該考慮能不能不通過建樹就直接算出節點總數。
定義一個單詞相對于另一個單詞的差:設單詞1的長度為L,且與單詞2從第N位開始不一致,則說單詞1相對于單詞2的差為L-N+1;,這是描述單詞相似程度的量。
可見,將一個單詞加入單詞樹的時候,須加入的節點等于該單詞樹中已有單詞的差的最小值。
單詞的字典順序排序后的序列則具有類似的特性,即在一個字典順序序列中,第m個單詞相對于第m-1個單詞的差必定是它對于前m-1個單詞的差中最小的。
于是,得出建樹的等效算法:
 1.讀入文件;
 2.對單詞列表進行字典順序排序;
 3.依次計算每個單詞對前一單詞的差,并把差累加起來。注意:第一個單詞相對于“空”的差為該單詞的長度;
 4.累加和再加上1(根節點),輸出結果。
數據結構
先確定32K(32*1024=32768字節)的文件最多有多少單詞和字母。
當然應該盡可能地存放較短的單詞。
因為單詞不重復,所以長度為1的單詞(單個單詞)最多26個;長度為2的單詞最多為26*26=676個;因為每個單詞都要一個換行符(換行符在計算機中占兩個字節),所以總共已經占用的空間:(1+2)×26+(2+2)×676=2782字節;剩余字節(32768-2782=29986字節)分配給長度為3的單詞(長度為3的單詞最多有26×26×26=17576個)有29986/(3+2)=5997。
所以單詞數量最多為26+676+5997=6699.
定義一個數組:string a[32768];把所有單詞連續存放起來,用選擇排序或快排對單詞進行排序。
代碼
#include <iostream> #include <cstdio> #include <string> using namespace std; int i,j,n,t,k; string a[8001]; string s; int main () {while(cin>>a[++n]); n--;for(i=1;i<n;i++){for(j=i+1;j<=n;j++){if(a[i]>a[j]){s=a[i];a[i]=a[j];a[j]=s;}}}t=a[1].length();for(i=2;i<=n;i++){j=0;while(a[i][j]==a[i-1][j]&&j<a[i-1].length()) j++;t+=a[i].length()-j;}cout<<t+1<<endl;return 0; }總結
以上是生活随笔為你收集整理的1337:【例3-2】单词查找树的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 1336:【例3-1】找树根和孩子
- 下一篇: 信息学奥赛一本通(C++)在线评测系统—
