1. 程式人生 > 其它 >利用自動機模型處理動態規劃的轉移路徑

利用自動機模型處理動態規劃的轉移路徑

這個套路俗稱 dp 套 dp。

大致思路就是把 dp 的轉移路徑用一個自動機模型處理出來。

眾所周知有 KMP、ACM、SAM 套 dp 的套路。而對於一些性質沒有這麼好的問題,就得自己設計一個並不那麼高效的自動機,去規劃 dp 的轉移路徑。

\(\text{遊園會}\)

字符集 \(\Sigma=\{N,O,I\}\)。給定模板串 \(T\),分別對於每個 \(p=0,1,\cdots,\left|T\right|\),求出滿足如下條件的字串 \(S\) 數量:

  1. 長度為 \(n\)
  2. 不存在 \(NOI\) 為它的子串
  3. \(\left|LCS(S,T)\right|=p\)(Longest Common Substring)

設計狀態 \(dp_{i,j,u}\) 用來計數。其中這裡的 \(u\) 主要是用於自動機上的轉移,可以看成自動機上的編號,希望把轉移路徑相同的 \(S\) 放到這上面。\(i,j\) 的定義是套路的,\(i\) 代表考慮大小為 \(i\) 的串,\(j\) 用來避免出現 \(NOI\) 子串。

如果列舉第 \(i\) 位的字元 \(S_i\),由於 LCS 的轉移為

\[lcs_{i,t}=\max(\max(lcs_{i-1,t},lcs_{i-1,t-1}+\left[S_i=T_t\right]),lcs_{i,t-1}) \]

因此自動機結點 \(u\) 上應該維護的資訊是:對於所有 \(t=0,1,\cdots,\left|T\right|\)

\(lcs_{t}\)(因為這個 \(i\) 是自動機結點的深度,所以把 \(i\) 省略掉了) 是多少。注意到給了 \(S_i\) 後,就可以從深度為 \(i-1\) 的自動機結點 \(u\) 確定唯一的深度為 \(i\) 的自動機結點 \(v\),計數就是一個直接的累加。

這樣,就完成了一個路徑規劃。

現在來考慮結點數量。注意到一個自動機結點 \(v\)\(lcs\) 陣列的轉移

\[{\color{red} lcs_{v,t}}=\max(\max(lcs_{u,t},lcs_{u,t-1}+\left[S_i=T_t\right]),{\color{red} lcs_{v,t-1}}) \]

因此 \(lcs\)

陣列單調不減。繼續觀察,可以證明,\(0\le lcs_{t}-lcs_{t-1}\le 1\)。因此根據差分陣列,這樣的陣列最多有 \(2^{\left|T\right|}\) 個。因此,自動機每層都只有 \(O(2^{\left|T\right|})\) 個結點。

最後的統計是容易的。總複雜度 \(O(2^{\left|T\right|}n)\)

\(\square\)