suffix-tree教程(個人總結)

背景

在計算機科學和生物信息學中,字符串處理是一個非常重要的領域。無論是搜索引擎、基因序列分析,還是壓縮算法,都離不開高效的字符串處理。傳統的字符串匹配算法,如暴力搜索、Knuth-Morris-Pratt (KMP) 算法和 Boyer-Moore 算法,雖然在特定場景下表現優異,但在處理大規模數據時常顯得捉襟見肘。后綴樹作為一種高級數據結構,以其高效的構建和查詢性能,成為處理復雜字符串問題的利器。

什么是后綴樹?

后綴樹是一種特殊的樹結構,用于表示一個字符串的所有后綴。給定一個長度為 n 的字符串 S,其后綴樹是一個有根的有向樹,包含 n 個葉子節點,每個葉子節點對應 S 的一個后綴。每個內部節點(除根節點外)至少有兩個孩子節點,每條邊都標記有 S 的一個非空子串。同一節點的兩條邊所標記的子串不能以相同的字符開頭。后綴樹的關鍵屬性是,從根到葉子的路徑所連接的邊標記拼接起來正好是 S 的一個后綴。

優勢與劣勢

優勢
  1. 快速構建:使用 Ukkonen 算法,后綴樹可以在 O(n) 時間內構建。
  2. 高效查詢:后綴樹允許在 O(m) 時間內進行子串搜索,其中 m 是查詢子串的長度。
  3. 豐富的應用:后綴樹在子串搜索、模式匹配、最長重復子串和最長公共子串等問題上表現出色。
  4. 空間優化:雖然后綴樹的空間復雜度為 O(n),但通過后綴數組等優化手段,可以進一步降低空間消耗。
劣勢
  1. 空間消耗較大:在最壞情況下,后綴樹的空間復雜度為O(n2),實際應用中通常為 O(n)。
  2. 實現復雜:Ukkonen 算法的實現較為復雜,對初學者有一定難度。
  3. 特定場景適用:后綴樹主要用于字符串處理問題,對于其他類型的數據處理,可能不如其他數據結構高效。

后綴樹的構建

后綴樹的構建可以通過 Ukkonen 算法在 O(n) 時間內完成。以下是構建后綴樹的詳細步驟:

初始化

從一個僅包含根節點的空樹開始。初始化活動點(active point),包括活動節點(active node)、活動邊(active edge)和活動長度(active length)。

逐字符插入

對字符串中的每個字符,將對應的后綴插入到樹中。每次插入新字符時,更新活動點并應用適當的擴展規則:

  1. 擴展規則 1:在活動點后插入一個新的邊。
  2. 擴展規則 2:在活動點后擴展現有的邊。
  3. 擴展規則 3:創建一個新的內部節點,并分裂現有的邊。
活動點更新

根據擴展后的新狀態,更新活動點的位置和狀態。如果活動點在根節點且活動長度大于0,則將活動長度減1,并將活動邊向前移動一位。如果活動點不是根節點,則將活動點移動到其后綴鏈接。

示例

以下是構建字符串 BANANA 的后綴樹的詳細過程:

  1. 初始化:從一個僅包含根節點的空樹開始。
  2. 插入后綴
    • 插入 A:
    Root└── A
    
    • 插入 NA:
    Root└── A└── NA
    
    • 插入 ANA:
    Root└── A└── NA└── N└── A
    
    • 插入 NANA:
    Root└── A└── NA└── N└── A└── NA
    
    • 插入 ANANA:
    Root└── A└── N└── ANA└── N└── A└── NA
    
    • 插入 BANANA:
    Root└── A└── N└── ANA└── B└── ANANA└── N└── A└── NA
    

Ukkonen 算法

Ukkonen 算法是一個在線算法,通過逐步擴展后綴樹來處理字符串中的每個字符。該算法的核心思想是維護一個活動點,通過該活動點跟蹤當前正在處理的后綴。每次插入新字符時,算法根據當前活動點的位置和狀態選擇適當的規則進行處理。

詳細步驟
  1. 初始化:創建一個根節點,并將活動點設置為根節點。
  2. 逐字符擴展:對字符串中的每個字符,執行以下步驟:
    • 擴展規則:根據當前活動點的位置和狀態選擇適當的擴展規則:
      • 規則 1:在活動點后插入一個新的邊。
      • 規則 2:在活動點后擴展現有的邊。
      • 規則 3:創建一個新的內部節點,并分裂現有的邊。
    • 活動點更新:根據擴展后的新狀態,更新活動點的位置和狀態。
示例代碼

以下是 Ukkonen 算法的 Python 實現:

class SuffixTreeNode:def __init__(self):self.children = {}self.suffix_link = Noneself.start = Noneself.end = Noneclass SuffixTree:def __init__(self, text):self.text = textself.root = SuffixTreeNode()self.build_suffix_tree()def build_suffix_tree(self):n = len(self.text)self.root.end = -1self.root.suffix_link = self.rootactive_node = self.rootactive_edge = -1active_length = 0remainder = 0for i in range(n):last_new_node = Noneremainder += 1while remainder > 0:if active_length == 0:active_edge = iif self.text[active_edge] not in active_node.children:leaf = SuffixTreeNode()leaf.start = ileaf.end = nactive_node.children[self.text[active_edge]] = leafif last_new_node:last_new_node.suffix_link = active_nodelast_new_node = Noneelse:next_node = active_node.children[self.text[active_edge]]edge_length = next_node.end - next_node.startif active_length >= edge_length:active_edge += edge_lengthactive_length -= edge_lengthactive_node = next_nodecontinueif self.text[next_node.start + active_length] == self.text[i]:if last_new_node:last_new_node.suffix_link = active_nodeactive_length += 1breaksplit = SuffixTreeNode()split.start = next_node.startsplit.end = next_node.start + active_lengthactive_node.children[self.text[active_edge]] = splitleaf = SuffixTreeNode()leaf.start = ileaf.end = nsplit.children[self.text[i]] = leafnext_node.start += active_lengthsplit.children[self.text[next_node.start]] = next_nodeif last_new_node:last_new_node.suffix_link = splitlast_new_node = splitremainder -= 1if active_node == self.root and active_length > 0:active_length -= 1active_edge = i - remainder + 1elif active_node != self.root:active_node = active_node.suffix_linkdef traverse_tree(self, node, suffixes, current_suffix):if not node.children:suffixes.append(current_suffix)returnfor char, child in node.children.items():self.traverse_tree(child, suffixes, current_suffix + self.text[child.start:child.end])def get_suffixes(self):suffixes = []self.traverse_tree(self.root, suffixes, "")return suffixestext = "BANANA"
st = SuffixTree(text)
suffixes = st.get_suffixes()
print(suffixes)

后綴樹的優化

雖然后綴樹具有許多優點,但其空間復雜度可能較高。為了優化空間,可以考慮以下幾種方法:

  1. 后綴數組:后綴數組是一種空間更為緊湊的數據結構,可以用來替代后綴樹。在某些應用中,后綴數組能夠提供類似的功能,并具有更低的空間開銷。
  2. 增強后綴數組:增強后綴數組結合了后綴數組和后綴樹的優點,提供了一種高效且空間優化的解決方案。
  3. 節點壓縮:通過合并后綴樹中的某些節點,減少節點數量,從而降低空間復雜度。

后綴數組

后綴數組是一個存儲字符串所有后綴的數組,每個后綴按字典順序排序。構建后綴數組的時間復雜度為O(nlogn),并且通過使用 Kasai 等人的算法,可以在 O(n) 時間內構建出后綴數組的高度數組(LCP 數組)。

示例代碼

以下是構建后綴數組的 Python 實現:

def build_suffix_array(text):n = len(text)suffixes = sorted([text[i:] for i in range(n)])suffix_array = [n - len(suffix) for suffix in suffixes]return suffix_arraytext = "BANANA"
suffix_array = build_suffix_array(text)
print(suffix_array)

應用實例

假設您需要在文本 BANANA 中查找模式 ANA 的所有出現位置。可以按照以下步驟使用后綴樹:

  1. 構建文本 BANANA 的后綴樹。
  2. 遍歷樹,沿著標記為 ANA 的邊進行搜索。
  3. 如果在消耗完模式后到達一個節點,則該節點下的葉子節點表示模式在文本中的起始位置。

后綴樹的更多應用

除了子串搜索、最長重復子串和最長公共子串外,后綴樹在其他字符串處理問題中也表現出色:

  1. 字符串壓縮:后綴樹可以用于構建 BWT(Burrows-Wheeler Transform),這是許多字符串壓縮算法的核心。
  2. 基因序列分析:在生物信息學中,后綴樹被廣泛用于基因序列的匹配和分析。
  3. 文檔相似性檢測:通過構建文檔的后綴樹,可以快速檢測兩個文檔之間的相似度。

結論

后綴樹是處理各種字符串處理問題的強大數據結構。通過了解其構建方法、性質和應用,可以顯著提升解決復雜字符串相關問題的能力。本文詳細介紹了后綴樹的構建、性質、應用及其優化方法,并提供了豐富的示例和代碼實現,旨在幫助讀者全面而深入地理解后綴樹。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/19864.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/19864.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/19864.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android14 WMS-IWindow介紹

IWindow是很重要的,官方介紹是API back to a client window that the Window Manager uses to inform it of interesting things happening. 也就是說是是用于WMS回調客戶端的,當窗口有一些改變時,WMS及時調用客戶端接口,讓客戶端…

Ubuntu22.04之解決:忘記登錄密碼(二百三十二)

簡介: CSDN博客專家,專注Android/Linux系統,分享多mic語音方案、音視頻、編解碼等技術,與大家一起成長! 優質專欄:Audio工程師進階系列【原創干貨持續更新中……】🚀 優質專欄:多媒…

gpt-4o api申請開發部署應用:一篇全面的指南

利用 GPT-4o API 開發創新應用:一篇全面的指南 OpenAI 的 GPT-4o 是一款集成了音頻、視覺和文本處理能力的多模態人工智能模型,它的出現代表了人工智能領域的重大進步。在本篇文章中,我們將詳細介紹如何通過 OpenAI API 使用 GPT-4o&#xf…

html中 table的 colspan和rowspan

Colspan 單元格跨越多列; Rowspan 單元格跨越多行 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title></title> </head> <body><h4>單元格跨兩列:</h4> <table border"1"&…

藍橋杯java組-字符串輸入輸出處理

題目描述&#xff1a;字符串的輸入輸出處理。 輸入&#xff1a;第一行是一個正整數N&#xff0c;最大為100。之后是多行字符串&#xff08;行數大于N&#xff09;&#xff0c; 每一行字符串可能含有空格&#xff0c;字符數不超過1000。 輸出&#xff1a;先將輸入中的前N行字符…

云動態摘要 2024-05-31

給您帶來云廠商的最新動態&#xff0c;最新產品資訊和最新優惠更新。 最新優惠與活動 [1.5折起]年中盛惠--AI分會場 騰訊云 2024-05-30 人臉核身、語音識別、文字識別、數智人、騰訊混元等熱門AI產品特惠&#xff0c;1.5折起 云服務器ECS試用產品續用 阿里云 2024-04-14 云…

鴻蒙開發接口媒體:【@ohos.multimedia.medialibrary (媒體庫管理)】

媒體庫管理 說明&#xff1a; 該組件從API Version 6開始支持。后續版本如有新增內容&#xff0c;則采用上角標單獨標記該內容的起始版本。 發前請熟悉鴻蒙開發指導文檔&#xff1a; gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md點擊或者復制轉到。 導入模塊 …

2.4 Docker部署JDK

2.4 Docker部署JDK jdk17部署&#xff08;自定義鏡像&#xff09; 1.在官網上下載jdk-17_linux-x64_bin.tar.gz&#xff0c;并安裝到/usr/local目錄下 cd /usr/local2.創建Dockerfile vim Dockerfile# 基于官方的Ubuntu 20.04鏡像作為基礎鏡像 FROM ubuntu:20.04# 設置環境…

【python深度學習】——大型工程項目管理以及互相導入

【python深度學習】——大型工程項目管理以及互相導入 1. 工程項目中常見的文件組織形式2. python中的“包”、“模塊”、與__init__.py2.1 概念理解2.2 \__init__py的使用3. 包的導入——相對導入與絕對導入3.1 相對導入3.1.1 相對導入的語法3.1.2 相對導入的使用注意事項與常…

Attentive Transfer Entropy to Exploit Transient Emergence of Coupling Effect

本文可以采用以下六個標準: 目標:指的是研究的基本目的。 耦合網絡重建專注于揭示網絡中變量之間潛在的連接結構,確定它們是如何相互關聯的。因果發現更進一步,不僅識別連接,還確定變量之間的因果關系和方向。信息傳遞測量量化變量之間流動的信息量,表明它們影響的強度和…

二維數組傳參時不用二級指針接收

先放結論&#xff1a; 1. 二維數組數組名指向的類型是 int [x] 類型&#xff0c;int** 指針指向類型是 int* &#xff0c;如果用二級指針接收會導致訪問錯誤&#xff0c;因為 int [x] 類型和 int* 類型不同。 2. 指向什么類型的指針1就按照該類型的字節數1移動。 最近在學…

初識java——javaSE(8)異常

文章目錄 一 異常的概念與體系結構1.1 什么是異常&#xff1f;1.2 異常的體系結構&#xff01;1.3 編譯時異常與運行時異常與Error編譯時異常&#xff1a;異常聲明&#xff1a;throws關鍵字 運行時異常&#xff1a;什么是Error? 二 處理異常2.1 異常的拋出&#xff1a;throw(注…

容器多機部署eureka及相關集群服務出現 Request execution failed with message: AuthScheme is null

預期部署方案&#xff1a;兩個eureka三個相關應用 注冊時應用出現&#xff1a;Request execution failed with message: Cannot invoke “Object.getClass()” because “authScheme” is null&#xff0c;一開始認為未正確傳遞eureka配置的賬戶密碼&#xff0c;例&#xff1a;…

5.23R語言-參數假設檢驗

理論 方差分析&#xff08;ANOVA, Analysis of Variance&#xff09;是統計學中用來比較多個樣本均值之間差異的一種方法。它通過將總變異分解為不同來源的變異來檢測因子對響應變量的影響。方差分析廣泛應用于實驗設計、質量控制、醫學研究等領域。 方差分析的基本模型 方差…

重慶人文科技學院建立“軟件安全產學研基地”,推動西南地區軟件安全發展

5月29日&#xff0c;重慶人文科技學院與開源網安簽訂了《產學研校企合作協議》&#xff0c;并舉行了“重慶人文科技學院產學研基地”授牌儀式&#xff0c;此次合作不僅深化了雙方在軟件安全領域的產學研緊密聯結&#xff0c;更是對川渝乃至西南地區軟件供應鏈安全發展起到重要的…

力扣linkedlist

反轉鏈表、 public class reverseList { // 1->2->3->o 、 o<-1<-2<-3public ListNode reverseList(ListNode head){//反轉鏈表ListNode prevnull;ListNode currhead;while(curr!null){ListNode nextcurr.next;curr.nextprev;prevcurr;currnext;}retu…

AI免費插件 批量條碼大師,支持100多種條碼類型

沒想到在網上看到一款和之前 悟空條碼 類似的條碼插件&#xff0c;叫批量條碼大師&#xff0c;他做的比 悟空條碼 功能更強&#xff0c;界面更美觀&#xff0c;特分享出來給大家。 本插件采用了BWIPJS條碼庫&#xff0c;支持110種條碼、二維碼的生成; 支持批量生成&#xff0c;…

愛堡集團數智掘金—共繪上市藍圖

&#xff08;本臺記者報&#xff09;2024年5月26日愛堡集團在浙江省杭州市上城區瑞萊克斯大酒店隆重召開規模達500人的盛會。這場聚焦智慧與創新的會議&#xff0c;旨在加速愛堡集團的數智化轉型進程&#xff0c;并為其上市之路繪制藍圖&#xff0c;吸引了眾多行業領袖和媒體的…

Qt 插件機制使用及原理

目錄 1.引言 2.插件原理 3.插件實現 3.1.定義一個接口集(只有純虛函數的類) 3.2.實現接口 4.插件的加載 4.1.靜態插件 4.1.1.靜態插件實現方式 4.1.2.靜態插件加載的過程 4.1.3.示例 4.2.動態插件 4.2.1.動態插件的加載過程 5.定位插件 6.插件開發的優勢 7.總結…

GPT-4o有點坑

GPT-4o有點坑 0. 前言1. GPT-4o簡介2. GPT-4o帶來的好處2.1 可以上傳圖片和文件2.2 更豐富的功能以及插件 3. "坑"的地方3.1 使用時間短3.2 GPT-4o變懶了 4. 總結 0. 前言 原本不想對GPT-4o的內容來進行評論的&#xff0c;但是看了相關的評論一直在說&#xff1a;技…