【演算法】字首樹

九年义务漏网鲨鱼發表於2024-10-30

基本內容

以樹的方式儲存字串的資料結構,方便字串的查詢及判斷是否為某一字串的字首

  • 入門例子 PHONELST - Phone List - 洛谷 | 電腦科學教育新生態

題目要求:判斷一組字串中是否存在某一字串是另一字串的字首。例如在{“911”, “91140”,“20”,“912”}中,“911”是“91140”的字首

  • 基本思想

將字串的每一個元素視為一個節點,例如“911”中將“9”,“1”,“1”視為不同的節點。依次將所有字串元素進行儲存。

  • 變數解釋

    ❗ ❗ ❗ 一個元素就是一個節點,只有不同字串的元素重複路徑的時候才屬於同一節點

    N:記錄一共最多可能有多少個節點;

    son:二維陣列,son[N] [10],記錄所有節的子節點的索引號idx,第二列為10是因為數字節點的子節點最多是10個,若是字母字串的話應該是son[N] [26]

    cnt:記錄第idx個節點是否為某一字串的結尾節點

    idx:當前的節點索引號(節點透過陣列儲存)

  • 核心程式碼

strs = ["911", "91140", "20", "912"]
for s in strs:
    p = 0 # 表示頭節點
    for i in range(len(s)):
        if son[p][int(s[i])] == 0: # 為0表示當前沒有該節點,idx為該節點的索引
            idx += 1
            son[p][int(s[i])] = idx
        p = son[p][int(s[i])] # 更新p為下一元素的節點索引
        
        # 判斷是否為其他字串的字首的兩種情況
        # ① 當前節點是其他字串的結束節點 ② 其他字串的節點是當前字串的結束節點
		if cnt[p] != 0 or (i == len(s) - 1 and son[p][int(s[i])] != 0):
            flag = True
            print("NO")
            break
    cnt[p] += 1 # 以索引號為p的節點結尾的字串加1,可以統計有多少個相同字串
if not flag:
    print("YES")
  • 總結
  1. 字首樹是一種以空間換時間的資料結構
  2. cnt 陣列不僅僅可以用於記錄是否為字串的結束節點,還可以記錄相同字串的個數

題目

  1. P10471 最大異或對 The XOR Largest Pair - 洛谷 | 電腦科學教育新生態

要求:在一組數找到兩個數的最大異或值,以長度為3的數字為例子,當與“001”配對的能達到最大異或值的數字為“110”,即為反碼

思路:從最高位開始,儘量找到與當前位數為反碼的

例子:在["001","101","100","111"] 中找到與 “111” 最大的異或對,從最高位開始,存在依次與11互為反碼的00節點,但在該路徑中到了第三層不存在與1互為反碼的0節點,因此只能繼續選擇 1 節點,因此最後能與111組成的最大異或對為001.

相關文章