hiho一下第二周 Hihocoder #1014 : Trie树
#1014 : Trie樹
時間限制:10000ms 單點時限:1000ms 內(nèi)存限制:256MB描述
小Hi和小Ho是一對好朋友,出生在信息化社會的他們對編程產(chǎn)生了莫大的興趣,他們約定好互相幫助,在編程的學(xué)習道路上一同前進。
這一天,他們遇到了一本詞典,于是小Hi就向小Ho提出了那個經(jīng)典的問題:“小Ho,你能不能對于每一個我給出的字符串,都在這個詞典里面找到以這個字符串開頭的所有單詞呢?”
身經(jīng)百戰(zhàn)的小Ho答道:“怎么會不能呢!你每給我一個字符串,我就依次遍歷詞典里的所有單詞,檢查你給我的字符串是不是這個單詞的前綴不就是了?”
小Hi笑道:“你啊,還是太年輕了!~假設(shè)這本詞典里有10萬個單詞,我詢問你一萬次,你得要算到哪年哪月去?”
小Ho低頭算了一算,看著那一堆堆的0,頓時感覺自己這輩子都要花在上面了...
小Hi看著小Ho的囧樣,也是繼續(xù)笑道:“讓我來提高一下你的知識水平吧~你知道樹這樣一種數(shù)據(jù)結(jié)構(gòu)么?”
小Ho想了想,說道:“知道~它是一種基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu),就像這里說的一樣!”
小Hi滿意的點了點頭,說道:“那你知道我怎么樣用一棵樹來表示整個詞典么?”
小Ho搖搖頭表示自己不清楚。
小Hi于是在紙上畫了一會,遞給小Ho,道:“你看這棵樹和這個詞典有什么關(guān)系?”
小Ho盯著手里的紙想了一會道:“我知道了!對于從樹的根節(jié)點走到每一個黑色節(jié)點所經(jīng)過的路徑,如果將路徑上的字母都連起來的話,就都對應(yīng)著詞典中的一個單詞呢!”
小Hi說道:“那你知道如何根據(jù)一個詞典構(gòu)建這樣一棵樹么?”
“不造!”
“想你也不知道,我來告訴你吧~”小Hi擺出一副老師的樣子,說道:“你先這么想,如果我已經(jīng)有了這樣的一個詞典和對應(yīng)的一棵樹,我要添加一個新的單詞apart,我應(yīng)該怎么做?”
“讓我想想……”小Ho又開始苦思冥想:“首先我要先看看已經(jīng)能走到哪一步了對吧?比如我從1號節(jié)點走"a"這一條邊就可以走到2號節(jié)點,然后從2號節(jié)點走"p"這一條邊可以走到3號節(jié)點,然后……就沒路可走了!這時候我就需要添加一條從3號節(jié)點出發(fā)且標記為"p"的邊才可以接著往下走……最后就是這樣了!然后我把最后到達的這個結(jié)點標記為黑色就可以了。”
小Hi說道:“真聰明~那你不妨再算算如果是一個有10W個單詞的詞典,每個單詞的長度不超過10的話,這棵樹會有多大?”
小Ho于是掏出筆來,一邊畫一遍念叨:“假設(shè)我已經(jīng)將前三個單詞構(gòu)成了這樣一棵樹,那么我要添加一個新的單詞的時候,最壞情況是這個單詞和之前的三個單詞都沒有公共前綴,那么這個新的單詞的長度如果是5的話,我就至少要添加5個結(jié)點到樹中才能夠繼續(xù)表示這個詞典!”
“而如果每次都是最壞情況的話,這棵樹最多也就100W個結(jié)點這么大!更何況最壞情況是不可能次次都發(fā)生的!畢竟字母表也才26個字母呢!”小Ho繼續(xù)說道。
“嗯~這樣我們是不是就可以用(單詞個數(shù)*單詞長度)個結(jié)點來表示一個詞典了呢?小Hi問道。
“是的呢!”小Ho道:“但是這樣一棵樹又有什么用呢?”
“可別小看了它,它就是傳說中的Trie樹哦~至于他有什么用,一會你就知道了!”小Hi笑嘻嘻的回答道。
“你看,我們現(xiàn)在得到了這樣一棵樹,那么你看,如果我給你一個字符串a(chǎn)p,你要怎么找到所有以ap開頭的單詞呢?”小Hi又開始考校小Ho。
“唔...一個個遍歷所有的單詞?”小Ho還是不忘自己最開始提出來的算法。
“笨!這棵樹難道就白構(gòu)建了!”小Hi教訓(xùn)完小Ho,繼續(xù)道:“看好了!”
小Hi在樹上用綠色標出了一個節(jié)點,遞給小Ho。
“這個結(jié)點……是從根節(jié)點先走"a"然后走"p"到達的結(jié)點呢!哦~~我知道了,以這個結(jié)點為根的子樹里所有標記結(jié)點都是以"ap"為前綴的單詞呢!而且所有以"ap"為前綴的單詞都在以這個節(jié)點為根的子樹里~”小Ho驚喜道。
“是的呢~那你對怎么解決我的問題有想法了么?”小Hi追問道。
“唔...那就是每次拿到你的字符串之后,我在樹上找到其對應(yīng)的那個結(jié)點,然后統(tǒng)計這個節(jié)點中有多少個標記節(jié)點?”小Ho不是很確定的答道:“但是這樣...似乎在最壞情況,也就是你每次給個字符串都很短的時候,我還是要掃描這棵樹的很大一部分呢?也就是說雖然平均時間復(fù)雜度降低了,但是最壞情況時間復(fù)雜度還是很高的樣子!”
小Hi笑嘻嘻道:”沒想到你自己看出來了呢~我還以為又要教訓(xùn)你了!~那你有什么好的解決方法么?”
“沒呢!小Hi你就別賣關(guān)子了,趕緊告訴我吧!”被折磨的夠嗆的小Ho開始求饒。
“好吧!就幫你這一回~”
“小Ho你有沒有想過這樣一個問題?不妨稱以T為根的子樹中標記節(jié)點的個數(shù)為L[T],既然我要統(tǒng)計某個L[T1],,而這個結(jié)點是不確定的,我有沒有辦法一次性把所有結(jié)點的L[T]求出來呢?”小Hi整理了下思緒,問道。
“似乎是有的,老師以前說過,遞歸什么的。。”小Ho答道。
“遞歸太復(fù)雜了!我們可以之后再說,你這么想,在你構(gòu)建Trie樹的時候,當你經(jīng)過一個結(jié)點的時候,說明了什么?”小Hi撇了撇頭,繼續(xù)問道。
“我想想,經(jīng)過一個結(jié)點……標記結(jié)點……說明了以這個結(jié)點為根的子樹中將要多出來一個標記結(jié)點?”
“沒錯!那你有沒有什么辦法來記錄這個改變呢?”
“我想想,我在最開始置所有L[T]=0,然后每次添加一個新的單詞的時候,都將它經(jīng)過的所有結(jié)點的L[T]全部+1,這樣我構(gòu)建完這棵Trie樹的時候,我也就能夠同時統(tǒng)計到所有L[T]了,對么?”小Ho開心道。
“那么現(xiàn)在!趕緊去用代碼實現(xiàn)吧!”小Hi如是說道
輸入
輸入的第一行為一個正整數(shù)n,表示詞典的大小,其后n行,每一行一個單詞(不保證是英文單詞,也有可能是火星文單詞哦),單詞由不超過10個的小寫英文字母組成,可能存在相同的單詞,此時應(yīng)將其視作不同的單詞。接下來的一行為一個正整數(shù)m,表示小Hi詢問的次數(shù),其后m行,每一行一個字符串,該字符串由不超過10個的小寫英文字母組成,表示小Hi的一個詢問。
在20%的數(shù)據(jù)中n, m<=10,詞典的字母表大小<=2.
在60%的數(shù)據(jù)中n, m<=1000,詞典的字母表大小<=5.
在100%的數(shù)據(jù)中n, m<=100000,詞典的字母表大小<=26.
本題按通過的數(shù)據(jù)量排名哦~
輸出
對于小Hi的每一個詢問,輸出一個整數(shù)Ans,表示詞典中以小Hi給出的字符串為前綴的單詞的個數(shù)。
樣例輸入
總結(jié)
以上是生活随笔為你收集整理的hiho一下第二周 Hihocoder #1014 : Trie树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 老BOJ 16 棋盘分割
- 下一篇: hiho一下第一周 Hihocoder