DP套DP

Lu_xZ發表於2024-10-07

該技巧通常用來求滿足某個要求的元素數量,而對於要求的判定需要 DP 解決。

因此我們將判定 DP 的結果作為計數 DP 的狀態來進行計數。

P4590 [TJOI2018] 遊園會

題意:給你一個字串 \(s\),求滿足條件的字串 \(t\) 的數量:\(\vert t\vert = n,\ \text{lcs}(s, t) = i,\ \text{"NOI"} \notin t\)

對每個 \(i \in [0, \vert s\vert]\) 求出答案。\(\vert s\vert \le 15,\ n \le 10^3,\ \sum = \{\text{N},\text{O}, \text{I}\}\)

\(f_{i, j}\) 表示 \(t\) 的字首 \(i\)\(s\) 的字首 \(t\) 的 lcs(最長公共子序列):

\[f_{i, j} = \begin{cases} f_{i - 1, j - 1} + 1 & t_i = s_j\\ \\ \max(f_{i - 1, j},\ f_{i, j - 1}) & t_i \ne s_j \end{cases} \]

要想得到 \(f_i\),我們只需知道 \(f_{i - 1}\)\(t_i\),且每種方案唯一對應一組 \(f_{i - 1}, t_i\)

\(f_{i}\) 壓入狀態減小複雜度。\(dp(i, f_i)\) 表示考慮了前 \(i\) 個字元,第 \(i\) 維 dp 陣列為 \(f_i\) 的方案數,列舉 \(t_i\) 轉移

合法的 \(f_{i}\) 實際很少,注意到 \(0\le f_{i, j} - f_{i, j - 1} \le 1\),每一種合法方案差分後能唯一對應一個長度為 \(\vert s\vert\) 的二進位制數。

對於子串的限制,再記錄一維 \(k\) 表示匹配到 "NOI" 的哪一位即可。

預處理每種 \(f_{i - 1}\) 以及 \(t_i\) 會轉移到哪個 \(f_i\),時間複雜度 \(O(2^{\vert s\vert} n)\)submission

CF578D LCS Again

題意:給定字串 \(s\),求滿足 \(\text{lcs}(s, t) = n - 1\) 的字串數量。\(n \le 10^5\)

繼續延續上題做法不是很牛,複雜度高達 \(2^nn\)

考慮哪些狀態是一定無用的。\(\text{lcs}(i, j) \le \min(i, j)\),字尾 \(i, j\) 能匹配的最大長度是 \(\min(n - i, n - j)\)

必須滿足 \(\min(i, j) + \min(n - i, n - j) = n - \vert i - j\vert \ge n - 1\) 才可能對答案產生貢獻。

需要考慮的狀態一共就三個:\(f_{i, i - 1},\ f_{i, i},\ f_{i, i + 1}\)

再注意到 \(f_{i, j} \ge \min(i, j) - 1\),否則也不能產生貢獻。

\(dp_{i, 0/1, 0/1, 0/1}\) 表示 三項分別為 \(\{i - 2, i - 1\},\ \{i - 1, i\},\ \{i - 1, i\}\) 的方案數,複雜度 \(O(\vert \sum\vert n)\)

submission