X快速前綴樹

喜歡這篇文章嗎?喜歡的話去看博主的置頂博客,即可依據分類找到此文章的原版得到更好的體驗,

圖片及代碼顯示的問題,筆者深感抱歉,想要更好的體驗去原博文即可。


title: X快速前綴樹
mathjax: true
date: 2020-03-16 17:51:11
categories: [myself_library,datastructure,tree,trie]
tags: [myself_library,datastructure,tree,trie]
keywords: [myself_library,datastructure,tree,trie]


X快速前綴樹

   我以前就說過,當你的數據結構達到了一定的基礎,就可以學習那些更加高級的數據結構了,往往那些更加高級的數據結構由基本數據結構組合而成。

先提出一個問題

   現在要你維護一個多重集合,支持3種操作,1詢問一個值(這個值不一定在集合中)的前驅和後繼,2向集合中插入一個元素,3從集合中刪掉一個元素,1操作10610^6次,2操作10510^5次,3操作10510^5,要求你在1S內完成回答。保證集合元素都小於M=10610^6

普通平衡樹?

   我們考慮到上面三種操作都是普通平衡樹常見的操作,很多人可能就直接拿起他自己的平衡樹上了。很遺憾,大概率是無法通過的。因爲操作次數太多了。

觀察,思考

   我們的操作需要的是大量的查詢,大量、大量,你個普通平衡樹怎麼操作的過來?

新的平衡樹

   現在我們提出一個新的平衡樹,這個平衡樹非常厲害,他支持O(lgM)O(lgM)的時間來刪除和插入,支持O(lglgM)O(lglgM)的時間來查詢前驅後繼。

X快速前綴樹

   字典樹+哈希表+維護葉子節點的雙向鏈表+二分
   首先,我們先建立一顆普通的01字典樹,這個樹我們對他稍作修改,考慮到字典樹的節點分3類: 葉子節點、根節點、內部節點,我們讓葉子節點間構造雙向環狀鏈表,其次,對於僅有左兒子的內部節點,讓其右兒子指向子樹的最小葉子節點,對於僅有右兒子的內部節點,讓其左兒子指向子樹的最大葉子節點。另一方面,我們對字典樹的每一層都建立一個hash表,hash掉他們節點所代表的值是有還是沒有,這樣我們就構造出了一個X快速前綴樹的模型了。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-h2BqgEaF-1584453120631)(/images/X快速前綴樹.png)]

X快速前綴樹的查找

   假設我們要找一個數k,我們在樹上尋找樹和k的lca[最低公共祖先],這個過程可以只要在hash表中二分即可知道lca在哪一個節點,可以證明,這個節點要麼沒有左兒子,要麼沒有右兒子。如果有的話,他的兒子和k的lcp[最長公共前綴]一定更長,但是這與他自己是lca的事實相悖。另一方面,由於我們的單兒子節點儲存了最值信息,如果這個節點沒有右兒子,則他的右兒子指向的值是k的前驅,至於後繼,在葉子節點的鏈表上後移一個單位即可。這個過程總複雜度在二分lca上,樹的高度爲lgn,二分高度,所以總體複雜度爲O(lglgn)O(lglgn)

X快速前綴樹的插入

   找出lca,若lca沒有右兒子,則說明當前節點要插入到右兒子裏面。照着做就行了,同時注意向下遞歸的時候把值也插入到hash表裏面,遞歸到葉子的時候重新連接雙向環狀鏈表(前驅和後繼),最後回溯的時候維護單兒子節點的信息,以及樹根方面的值就行了。

X快速前綴樹的刪除

   找到待刪除節點,然後刪掉,重新維護葉子鏈表,回溯的時候從hash表裏面刪掉自己,對於單兒子的節點也要根據子樹回溯即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章