21.7.8 t1
阿新 • • 發佈:2021-07-08
tag:SAM,矩陣乘法,分塊
首先我們要知道一個 trick,如何把兩個 SAM 拼起來。
大概就是對於第一個 SAM 上的所有點,如果某個字元 \(c\) 沒有出邊,就連向第二個 SAM 的根結點的 \(c\) 出邊指向的點。
這樣最後會構造出來一個自動機,每一條路徑都對應著一個題目中要求的字串。(為了方便,可以倒著構造)
先考慮如何求 \(f(l,r)\)。
暴力就是直接從右往左 dp。
然後仔細觀察會發現,第 \(i\) 個 SAM 的 dp 值,只與它的形態和第 \(i+1\) 個 SAM 的根的兒子的 dp 值有關。
也就是說 \(f[root_i]= a_1f[son[root_{i+1}][1]]+\cdots+a_Tf[son[root+{i+1}][T]]+1\)
所以可以用矩陣的形式,表示出第 \(i+1\) 個 SAM 的根的兒子,對第 \(i\) 個 SAM 的根的兒子的貢獻,而矩陣只與第 \(i\) 個 SAM 的形態有關。
這個部分可以 \(O(nT^2)\) 求出來。(hehezhou說可以 \(O(nT)\),不過不重要)
於是可以 \(O(lognT^2)\) 的時間求出 \(f(l,r)\)。
然後要求 \(\sum_{l,r}f(l,r)\),相當於求一個類似於 \(\sum_{l,r}\prod_{i\in[l,r]}A_i\) 的東西。
再多維護一點東西就行了,所以實際上只是比求 \(f(l,r)\) 多了億點常數。
可以分塊維護。
十分卡常。
誰想寫這個毒瘤的程式碼啊!