Google中的關(guān)鍵詞提示=VS中的代碼自動補全解滓?

一球订、引言

我最近用Google以來,不管是客戶端Chrome還是手機端Chrome旋讹,每次查找資料殖蚕,都只需要打幾個單詞就行,后面的在下拉框選就行沉迹,像下面這樣——

Google搜索示意圖

我起初感覺這個提示的實現(xiàn)睦疫,是智能算法中的預(yù)測功能——通過輸入的前幾個字符對后面的進行預(yù)測。

但是今天看了看專欄后鞭呕「蛴恍然大悟,也許算法的優(yōu)化真的有用到預(yù)測功能,但是它起初用到的不是瓦糕,而是我們上次說過的——字符串匹配底洗。

  • 匹配的本質(zhì)是什么?針對于字符串呢咕娄?

匹配的本質(zhì)就是找相同的地方亥揖。
針對于字符串,我認(rèn)為就是在多個字符串中search公共的子串圣勒。注意:不是單個字符费变,而是前綴子串后綴子串

那么好圣贸,匹配解釋完了挚歧,大家可以猜一下,這個功能是用了什么數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的吁峻?
其實我們不需要知道這個數(shù)據(jù)結(jié)構(gòu)的名字滑负,只需要知道它的特點是什么。那么我們來問下自己——

  • 這個數(shù)據(jù)結(jié)構(gòu)需要posses的特點是什么锡搜?

特點就是可以在一組字符串集合中快速查找某個字符串橙困。

那么有這種DS嗎?有的——Trie樹耕餐。

二凡傅、Trie樹的本質(zhì)

2.1 如何使用trie樹解決實際問題?

For example肠缔,我們有6個字符串夏跷,分別是: how, hi, her, hello, so, see。
既然是應(yīng)用Trie樹明未,We就把這6個字符串組織成屬于它們自己的Trie樹槽华,i.e.,查找的時候趟妥,在一個樹形結(jié)構(gòu)里面查找猫态。

使用Trie樹解決6個字符串的匹配問題

我們來分析一下上圖——

  • 根節(jié)點不包含任何信息
  • 每個節(jié)點的內(nèi)容都表示一個字符串的字符
  • 根節(jié)點到紅色節(jié)點的一個path表示一個字符串

那么我想問大家一個問題:

  • 圖中的紅色節(jié)點均是葉子節(jié)點嗎披摄?

2.2 如何構(gòu)造Trie樹亲雪?

我上節(jié)有提到一句話,就是針對這6個字符串疚膊,構(gòu)造的是屬于它們自己的Trie樹义辕,什么意思呢?
構(gòu)造Trie樹的每一個step寓盗,都是往Trie里面插入一個字符串灌砖。當(dāng)6個字符串插入finish以后璧函,Trie就build好了。

Trie樹構(gòu)造示意圖1

Trie樹構(gòu)造示意圖2

2.3 如何在構(gòu)造好的Trie樹中查找基显?

首先問兩個questions,

  • 在一棵樹中查找蘸吓,我們匹配的載體是什么?

用樹來存儲數(shù)據(jù)续镇,數(shù)據(jù)都放在節(jié)點中美澳,所以載體就是節(jié)點销部。

在Trie樹中摸航,節(jié)點存放的都是單個字符
So, 如果我們要查找字符串"her"舅桩,

  • 第一步: 將her分割成h, e, r
  • 第二步: 從Trie樹的根節(jié)點開始match酱虎。


    查找字符串示意圖1

好,her的最后一個字符r是紅色節(jié)點擂涛,那么如果所查找的字符串的最后一個字符不是紅色節(jié)點呢读串?
比如,查找he撒妈。

查找字符串示意圖2

如果出現(xiàn)這種情況恢暖,我們就可以believe that這個字符串“he”是某個字符串的前綴子串,但是并不能完全匹配任何字符串狰右。

2.4 如何用代碼實現(xiàn)一棵Trie樹杰捂?

我們在實現(xiàn)Trie樹前,先考慮一下棋蚌,

  • We實現(xiàn)的Trie樹嫁佳,都要做什么工作?

在我看來谷暮,兩個——

  1. 將一個又一個字符串插入到Trie樹中蒿往。2. 在Trie樹中查詢一個字符串。

那么接下來湿弦,

  • 如何存儲一個Trie樹瓤漏?

Trie樹是一棵多叉樹。二叉樹的存儲中颊埃,一個節(jié)點的左右子節(jié)點是通過指針來存儲的蔬充。
那么對于多叉樹呢?我們can借助散列表的思想竟秫,通過一個下標(biāo)與字符一一映射的數(shù)組娃惯,沒錯,是數(shù)組肥败,來存儲子節(jié)點的pointer趾浅。

如何存儲多叉樹的子節(jié)點

上圖參照圖

假設(shè)愕提,字符串中有a-z26個小寫字母,也就是26個字符皿哨。
We在下標(biāo)為0的位置浅侨,存儲指向子節(jié)點a的指針,
在下標(biāo)為1的位置证膨,存儲指向子節(jié)點b的指針如输,
...
...
...
在下標(biāo)為25的位置,存儲指向子節(jié)點z的指針央勒。
If, 某個字符的子節(jié)點不存在不见,我們就在對應(yīng)的下標(biāo)位置存儲null


存儲完Trie樹后崔步,我們要做的就是查找了稳吮。

  • 查找的準(zhǔn)則:通過待查找字符的ASCII碼值減去“a”的ASCII碼值,從而快速查找到匹配的子節(jié)點的指針井濒。

舉個栗子:d 的 ASCII 碼減去 a 的 ASCII 碼就是 3灶似,那子節(jié)點 d 的指針就存儲在數(shù)組中下標(biāo)為 3的位置中。

2.5 Trie樹的時間復(fù)雜度是多少瑞你?

構(gòu)建 Trie 樹的過程酪惭,需要掃描所有的字符串,時間復(fù)雜度是 O(n)(n 表示所有字符串的長度和)者甲。

每次查詢時春感,如果要查詢的字符串長度是 k,那我們只需要比對大約 k 個節(jié)點过牙,就能完成查詢操作甥厦。

也就是說,Trie樹的時度跟原本那組字符串的長度和個數(shù)沒有任何關(guān)系寇钉。所以說刀疙,構(gòu)建好 Trie 樹后,在其中查找字符串的時間復(fù)雜度是 O(k)扫倡,k 表示要查找的字符串的長度谦秧。

三、Trie樹和內(nèi)存是死敵嗎撵溃?

是的疚鲤。

四、如何改善Trie樹缘挑?

既然集歇,Trie樹消耗內(nèi)存比較嚴(yán)重,那么其本質(zhì)是why? 猜一下就知道语淘,因為是數(shù)組存儲的诲宇。
我們不用數(shù)組存儲际歼,換一個。

有序數(shù)組姑蓝、跳表鹅心、散列表、紅黑樹

當(dāng)然纺荧,這四個數(shù)據(jù)結(jié)構(gòu)的使用旭愧,查詢效率就會低一些。

假設(shè)有序數(shù)組入選宙暇,數(shù)組中的指針按照所指向的子節(jié)點中的字符的大小順序排列输枯。
查詢的時候,我們可以通過二分查找的方法客给,快速查找到某個字符應(yīng)該匹配的子節(jié)點的指針用押。
但是肢簿,在往 Trie 樹中插入一個字符串的時候靶剑,我們?yōu)榱司S護數(shù)組中數(shù)據(jù)的有序性,插入的操作就會稍微慢了點池充。


Trie樹還有一個變體桩引,which can 解決內(nèi)存消耗,縮點優(yōu)化——
就是對只有一個子節(jié)點的節(jié)點收夸,而且此節(jié)點不是一個串的結(jié)束節(jié)點坑匠,可以將此節(jié)點與子節(jié)點合并。(這樣可以節(jié)省空間卧惜,但卻增加了編碼難度厘灼。)

縮點優(yōu)化

五、散列表咽瓷、紅黑樹可以替代Trie樹嗎设凹?

Actually,字符串的匹配問題茅姜,就是數(shù)據(jù)的查找問題闪朱。

支持動態(tài)數(shù)據(jù)高效操作的數(shù)據(jù)結(jié)構(gòu),比如散列表钻洒、紅黑樹奋姿、跳表等等。
實際上素标,這些數(shù)據(jù)結(jié)構(gòu)也可以實現(xiàn)在一組字符串中查找字符串的功能称诗。

Trie樹和紅黑樹and跳表相比,在處理情景一組字符串中查找字符串中头遭,Trie樹對要處理的字符串有4個比較嚴(yán)格的要求——

  1. 字符串中包含的字符集不能太大寓免。
    Because如果字符集太大退腥,那存儲空間可能就會浪費很多。
    即便可以優(yōu)化再榄,但也要付出犧牲查詢狡刘、插入效率的代價。
  1. 要求字符串的前綴重合比較多困鸥,不然空間消耗會變大很多嗅蔬。
  1. 如果要用 Trie 樹解決問題,那我們就要自己從零開始實現(xiàn)一個 Trie 樹疾就,還要保證沒有 bug澜术,這個在工程上是將簡單問題復(fù)雜化,除非必須猬腰,一般不建議這樣做鸟废。
  1. 通過指針串起來的數(shù)據(jù)塊是不連續(xù)的,而 Trie 樹中用到了指針姑荷,所以盒延,對緩存并不友好,性能上會打個折扣鼠冕。

綜合以上4點添寺,針對在一組字符串中查找字符串的問題,更傾向于用散列表或者紅黑樹懈费。

In fact计露,Trie 樹只是不適合精確匹配查找,這種問題更適合用散列表或者紅黑樹來解決憎乙。
Trie 樹比較適合的是查找前綴匹配的字符串票罐,也就是類似Google中的搜索詞提示的那種場景。

六泞边、如何利用 Trie 樹该押,實現(xiàn)搜索關(guān)鍵詞的提示功能?

We假設(shè)關(guān)鍵詞庫由用戶的熱門搜索關(guān)鍵詞組成繁堡,我們將這個詞庫構(gòu)建成一個 Trie 樹沈善。

當(dāng)用戶輸入其中某個單詞的時候,把這個詞作為一個前綴子串在 Trie 樹中匹配椭蹄。

  • We假設(shè)詞庫里只有 hello闻牡、her、hi绳矩、how罩润、so、see 這 6 個關(guān)鍵詞翼馆。當(dāng)用戶輸入了字母 h 的時候割以,我們就把以 h 為前綴的 hello金度、her、hi严沥、how 展示在搜索提示框內(nèi)猜极。
  • 當(dāng)用戶繼續(xù)鍵入字母 e 的時候,我們就把以 he 為前綴的 hello消玄、her 展示在搜索提示框內(nèi)跟伏。
搜索關(guān)鍵詞提示原理圖

以上就是搜索關(guān)鍵詞提示的最基本的算法原理。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末翩瓜,一起剝皮案震驚了整個濱河市受扳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌兔跌,老刑警劉巖勘高,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異坟桅,居然都是意外死亡华望,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進店門桦卒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來立美,“玉大人,你說我怎么就攤上這事方灾。” “怎么了碌更?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵裕偿,是天一觀的道長。 經(jīng)常有香客問我痛单,道長嘿棘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任旭绒,我火速辦了婚禮鸟妙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘挥吵。我一直安慰自己重父,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布忽匈。 她就那樣靜靜地躺著房午,像睡著了一般。 火紅的嫁衣襯著肌膚如雪丹允。 梳的紋絲不亂的頭發(fā)上郭厌,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天袋倔,我揣著相機與錄音,去河邊找鬼折柠。 笑死宾娜,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的扇售。 我是一名探鬼主播碳默,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼缘眶!你這毒婦竟也來了嘱根?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤巷懈,失蹤者是張志新(化名)和其女友劉穎该抒,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體顶燕,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡凑保,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了涌攻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片欧引。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖恳谎,靈堂內(nèi)的尸體忽然破棺而出芝此,到底是詐尸還是另有隱情,我是刑警寧澤因痛,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布婚苹,位于F島的核電站,受9級特大地震影響鸵膏,放射性物質(zhì)發(fā)生泄漏膊升。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一谭企、第九天 我趴在偏房一處隱蔽的房頂上張望廓译。 院中可真熱鬧,春花似錦债查、人聲如沸非区。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽院仿。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間歹垫,已是汗流浹背剥汤。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留排惨,地道東北人吭敢。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像暮芭,于是被迫代替她去往敵國和親鹿驼。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內(nèi)容