參考資料1
參考資料2
前置知識:字首函式,border的簡單認識
約定:字串的下標從 \(0\) 開始。\(|s|\) 表示字串 \(s\) 的長度。
對於字串 \(s\),記其每乙個字元分別為 \(s_0, s_1, \cdots, s_\)。
子串 \(s_l, s_, \cdots, s_, 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\) 的長度。
先來求出每個字首的所有 \(\text\)。
顯然,長度為 \(i\) 的字首的所有 \(\text\) 的長度為 \(\pi(i-1),\pi(\pi(i-1)-1),\cdots\);
長度為 \(j\) 的字首的所有 \(\text\) 的長度為 \(\pi(j-1),\pi(\pi(j-1)-1),\cdots\)
所以要求出這兩個字首的最長公共 \(\text\) 的長度,只需要兩個指標來從大往小跳,第一次遇到的時候……很自然地就可以使用lca的技術來進行解決。
我們只需要對每個長度 \(1\leqslant i \leqslant |s|\) 進行 \(i\leftrightarrow\pi(i-1)\) 的連邊,再以 \(0\) 為根做lca就可以了。
需要注意的是如果要求的兩個點中其中乙個點是另乙個點的祖先,答案將為lca的父親,因為自己不是自己的 \(\text\)。
code:
(咕咕咕)
P5829 模板 失配樹
p5829 模板 失配樹 參考題解 我們先想乙個問題 如何求出乙個字串的所有border?如果乙個字串既是 s的字首又是 s 的字尾,那麼我們把 ss 自己平移一下就可以前後重合,然後我們就可以繼續匹。這不就是kmp嗎 求兩個字首的最長公共border,先對原串進行kmp,通過跳兩個字首的next求...
P5829 模板 失配樹
p5829 模板 失配樹 求公共 border 求 border 我會,kmp 那麼我直接做 m 次 kmp。顯然會tle,但是我們也可以用 kmp 先求一下原串的 border 然後我們可以發現,border 的 border 也是 border 那麼我們可以利用這個關係建一棵樹,然後我們可以發現...
P5829 模板 失配樹
目錄雖然不知道失配樹是什麼,看這題是為數不多的kmp練手的 能做的題 之一,就把這道題切了 傳送門個人覺得題目已經非常簡潔明瞭,感動,就不再重複題意 kmp lca 先推一道題,對這題應該有幫助 傳送門 kmp中,next i 是由next 1 i 1 得到的,若next i 由next j 得到,...