[Exercises on 2022.5.11] 字串轉風車煮飯吃蒸飯吃脂肪層
例 1.
\(\text{CF504E Misha and LCP on Tree}\)
首先可以想到預處理從根到每個點和每個點到根的雜湊值(需要處理向上和向下的兩種情況),然後進行二分,用長鏈剖分 \(\mathcal O(1)\) 找祖先即可做到 \(\mathcal O((n+m)\cdot \log n)\)。或者對整棵樹重鏈剖分,維護 \(\rm dfs\) 序列上的雜湊值(當然之前的方法也可行),這樣路徑會被劃分成 \(\mathcal O(\log n)\) 條重鏈,對兩條路徑進行掃描,一直到不同的重鏈再進行二分,兩個 $\log $ 是分開的,總共是 \(\mathcal O(m\log n)\)
例 2.
\(\text{CF204E Little Elephant and Strings}\)
一些閒話:我字串真的好垃圾啊!猛然發現自己只有字串模板題水平 o(TヘTo)。
考慮 \(\rm SA\)。將所有字串接在一起,中間的字元必須兩兩不同,然後做一個 \(\rm SA\)。固定左端點 \(l\),向右延伸找到恰好使得 排名 在 \([l,r]\) 之中的字尾所屬字串種類為 \(k\) 的 \(r\)。容易發現,這樣的 \(r\) 是遞增的,所以可以維護一個雙指標。對於每個尺取到的 \([l,r]\)
現在的問題是我們如何將滿足題意的子串貢獻到每個字串上,還是考慮 \([l,r]\) 是一段區間比較好維護,所以可以將貢獻累加在後綴上(因為我們是取 \(\rm max\),所以不存在算重的問題,令這個陣列為 \(f\)),用個隨便什麼東西維護區間取 \(\max\),單點查值都行。最後將字尾上的貢獻累加到字串上即可。
完了嗎?
事實上,上文的演算法並不完全正確。還是考慮尺取到的 \([l,r]\),我們只保證這是 "以每個 \(l\) 開始,恰好使得 排名
同時,我們也可以發現根本不需要維護區間取 \(\max\),只用更新 \(f_i\) 即可!
另外,向左拓展一定是不優的,這個很容易證明。再另外 \(k=1\) 的情況有些特殊,需要另行考慮。