基本內容
以樹的方式儲存字串的資料結構,方便字串的查詢及判斷是否為某一字串的字首
- 入門例子 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")
- 總結
- 字首樹是一種以空間換時間的資料結構
cnt
陣列不僅僅可以用於記錄是否為字串的結束節點,還可以記錄相同字串的個數
題目
- P10471 最大異或對 The XOR Largest Pair - 洛谷 | 電腦科學教育新生態
要求:在一組數找到兩個數的最大異或值,以長度為3的數字為例子,當與“001”配對的能達到最大異或值的數字為“110”,即為反碼
思路:從最高位開始,儘量找到與當前位數為反碼的
例子:在["001","101","100","111"] 中找到與 “111” 最大的異或對,從最高位開始,存在依次與
11
互為反碼的00
節點,但在該路徑中到了第三層不存在與1
互為反碼的0
節點,因此只能繼續選擇1
節點,因此最後能與111
組成的最大異或對為001
.