08.01

purplevine發表於2024-08-04

?

給定一個長度為 \(n\) 的字串序列 \(S\),字符集為小寫字母。\(m\) 次詢問,每次給定含恰好一個萬用字元的串 \(T\),詢問 \(T\) 能和多少 \(S_i\) 匹配。

\(\sum |S_i|+|T| \leq 3 \cdot 10^6\)\(n, m \leq 10^5\)

對於每個串 \(s\) 和每個 \(i < |s|\),在 Trie 樹的 \(s_{1 \dots i}\) 處打一個標籤 \(s_{i+1\dots |s|}\),雜湊維護之。

複雜度線性。

gym103409H

把串分成很多個形如 \([r \cdot 2^k, (r + 1)\cdot 2^k)\) 的樣子。對詢問串建 AC 自動機,我們需要求出模式串經過 AC 自動機的每個點多少次。

\(f_{u, k, 0/1}\):從 ACAM 的點 \(u\) 出發,走 \(s_{0 \sim 2^k-1}\)\(s'_{0 \sim 2^k-1}\) 步會到達哪個節點。有 \(f_{u, k, 0} = f_{f_{u, k-1, 0}, k-1, 1}\)

考慮 \(c_{u, k, 0/1}\) 為使用 \(f_{u, k, 0/1}\) 轉移的次數,考慮用

\[g_{u, k-1, 0} = c_{u, k-1, 0} + g_{u, k, 0} + \sum_{f_{v, k, 1}=u} g_{v, k, 1} \]

更新 \(g_{u, k, 0/1}\),最後 \(g_{u, 0, 0} + g_{u, 0, 1}\) 即為經過的次數。

CF1801G

考慮 \(s_{1\dots r}\) 的匹配數減去 \(s_{1\dots l-1}\) 的匹配數,多餘的部分跨越 \(l\)

分解 \((A, B)\)\(A\)\(s_{1 \dots l-1}\) 的字尾,\(B\)\(s_{l \dots n}\) 的字首,且 \(A+B \in \{s_i\}\)

gym104090l

P4770

首先對每個 \(r\) 求一個最小的 \(l\) 使得 \(T[l, r] \in S\)

尋找的方法是,增量,跳 fail 跳到有 \(T_r\) 的出邊,走過去。(直接跳好像就是對的)

這樣可以對一個 \(s\) 做,利用 SAM 遍歷 \(T\) 的所有子串並透過 \(l\) 就行了。

接下來要擴充到 \(s[l, r]\) 的情況。

還是考慮維護所有 \(l\)。我們掃右端點並同時維護每個子串最靠右的出現,考慮動態更新每個點子樹內 endpos 值最大且不超過 \(r\) 的數值 \(c_i\),則每次要把一個點 fail 樹上到根的所有祖先一起賦值。設當前串的長度為 \(m\),列舉到的右端點為 \(r_0\),當前在詢問 \(s[l, r]\),找到 \(s[l+m-1, r]\) 區間的 endpos 集合是否有 \(r_0\)。至於 \(T[1, r_0]\) 有幾個字首出現過,利用 \(c\) 求當前區間與 \(T[1, r_0]\) 的最長公共字尾就行了。

P6292

gym104901L

分段 dp:\(f_{i, j, 0/1}\) 表示前 \(i\) 段選 \(j\) 段且最後一段是否被選,有

\[f_{i, j, 1} = \max\{ f_{i', j-(i-i'), 0} + w(i', i) \} \\ f_{i, j, 0} = \max\{ f_{i-1, j, 1}, f_{i-1, j, 0} \} \]

考慮到第一種轉移中 \(i-j\) 不變,以 \(i-j\) 為第一維做 dp,同時試圖用資料結構維護最優的選擇點。

考慮 \(w(i', i)\) 的變化,當 \(i\) 為某個集合的 \(r\) 時,所有 \(i'<l\)\(w(i', i)\) 都會增加,也就是字首加。

需要維護的是,後面插數,字首加,全域性最大值,線段樹維護之,複雜度 \(O(n^2 \log n + nm)\)