趣題 Anagram輔助程式的資料結構

2021-05-10 08:17:37 字數 1246 閱讀 4332

anagram是乙個比較流行的英文文字遊戲,本blog之前曾經介紹過,這裡我再提一下。anagram就是把乙個詞或者一句話裡的字母重新排列,組成乙個新的單詞或句子,通常前後兩者有一種諷刺的意味。比如,dormitory = dirty room,或者desperation = a rope ends it。創作乙個有意思的anagram並不是一件容易的事,你很可能需要計算機的幫助才能找到合適的詞。例如,我們可以利用hash表瞬間找出與給定單詞所使用的字母完全相同的單詞。我們可以把字典中每個單詞的字母按照字母順序重新排列,於是對單詞dame和made操作後的結果都是adem,這樣的話使用字母完全相同的單詞就對應了乙個唯一的hash值,我們就可以方便地把它們歸在一起。

而實際上,這個hash表往往沒什麼用。乙個anagram很可能是由多個單詞構成的,因此我們更希望知道,使用某個單詞中的字母(不一定全部使用)可以構造出哪些新的單詞。例如,我輸入單詞dormitory,則程式可以輸出dirty, motor, trim, dry, room等單詞。很多anagram輔助程式都有這樣的功能,並且這也單獨作為乙個文字遊戲存在。我們稱這種只用到一部分給定字母的單詞叫做不完全anagram。假如字典裡共有n個單詞,輸入資料長度為l,那麼你怎樣才能找出所有的不完全anagram?一種方法是遍歷所有n個單詞,依次判斷每個單詞是否合法;另一種方法則是列舉輸入資料的2^l子集,對每個子集在之前建立的hash表中查詢一次。現在,你能否想出乙個資料結構,使得你的anagram輔助程式能夠以最快的速度輸出任何乙個給定單詞的不完全anagram?

答案比你想像的更簡單,這是乙個非常簡單的資料結構。我們建立一棵高度為26的樹,按照每個字母出現的次數像trie一樣插入到樹中。比如,abacus有2個a,於是插入到根的第二個子樹裡,接下來數出字母b的個數為1,並繼續沿標號為1的邊往下走,依此類推。最後,所有的資料都存放在對應的葉子節點上。查詢時,在每個節點上只需數一數輸入資料中對應字母的個數n,沿著標號小於等於n的邊往下走就行了。

下面是乙個非常有趣的問題:這個資料結構還有什麼優化的餘地?比如,單詞在樹中是按照從a到z的順序依次分類,但實際上我們可以任意調整這個順序。那麼,你覺得建這棵樹時是先按e、t等常用字母的個數分類好,還是先按照q、z等不常用字母的個數分類好?這個問題很簡單,留給大家思考吧。

另乙個比較類似的東西是用於拼寫檢查的資料結構。這兩個有趣的資料結構都是我在這裡看到的。

做人要厚道

轉貼請註明出處

錢學森做過的趣題

班裡有30個男同學和30個女同學,有一次男女分成前後兩排,發現每個男同學都比前面的女同學高。現在各排同學按照從左到右,從高到低的順序調整,會出現某個男同學不高於前面的女同學嗎?不會。經分析易知,最高的男生比最高的女生高,最矮的男生也比最矮的女生高,因此可以畫出以下圖形,這個圖形也是重排後的站位情況 ...

程式設計師的演算法趣題Perl版 (二)

竟然一月一更。第四題 假設一根木棒n厘公尺,需要切分為一厘公尺長的木棒,每根木棒只可以乙個人切,木棒切成兩根可以兩個人切 求 n厘公尺長木棒,m個人最少要切幾次,比如n 8,m 3,則需要切4次。perl 20170930 use strict sub cut elsif currentparts ...

100 的程式設計師都想挑戰的演算法趣題!

計算機的世界每天都在發生著深刻的變化。新作業系統的發布 cpu效能的提公升 智慧型手機和平板電腦的流行 儲存介質的變化 雲的普及 這樣的變化數不勝數。在這樣日新月異的時代中,演算法 是不變的重要基石。要編寫高效率的程式,就需要優化演算法。無論開發工具如何進化,熟識並能靈活運用演算法仍然是對程式設計師...