Border樹(失配樹)

參考資料1
參考資料2

前置知識:前綴函數,Border的簡單認識

約定:
字符串的下標從 \(0\) 開始。\(|s|\) 表示字符串 \(s\) 的長度。
對於字符串 \(s\),記其每一個字符分別爲 \(s_0, s_1, \cdots, s_{|s|-1}\)
子串 \(s_l, s_{l+1}, \cdots, s_{r-1}, s_r\) 簡記爲 \(s[l:r]\)。特別地,若 \(l=0\),可記作 \(s[:r]\);若 \(r=|s|-1\),可記作 \(s[l:]\)
對於字符串 \(a, b\)\(a+b\) 表示拼接操作,即將字符串 \(b\) 拼接到字符串 \(a\) 之後,構成新的字符串。
記構成的新字符串爲 \(c\),則上述拼接操作記爲 \(c\gets a+b\)
其中符號 \(x\gets y\) 表示將 \(y\) 的值賦給 \(x\)
不論是字符還是字符串,皆不加引號。

不妨直接來看模板
我們的目標是快速求出 \(s[:p]\)\(s[:q]\) 的最長公共 \(\text{Border}\) 的長度。

先來求出每個前綴的所有 \(\text{Border}\)
顯然,長度爲 \(i\) 的前綴的所有 \(\text{Border}\) 的長度爲 \(\pi(i-1),\pi(\pi(i-1)-1),\cdots\)
長度爲 \(j\) 的前綴的所有 \(\text{Border}\) 的長度爲 \(\pi(j-1),\pi(\pi(j-1)-1),\cdots\)
所以要求出這兩個前綴的最長公共 \(\text{Border}\) 的長度,只需要兩個指針來從大往小跳,第一次遇到的時候……很自然地就可以使用LCA的技術來進行解決。
我們只需要對每個長度 \(1\leqslant i \leqslant |s|\) 進行 \(i\Leftrightarrow\pi(i-1)\) 的連邊,再以 \(0\) 爲根做LCA就可以了。
需要注意的是如果要求的兩個點中其中一個點是另一個點的祖先,答案將爲LCA的父親,因爲自己不是自己的 \(\text{Border}\)
code:
(咕咕咕)

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