The 2020 ICPC Asia Macau Regional Contest B Boring Problem


比較模板的題。

題目
給定一個字符串 \(S\)\(n\) 個字符串 \(T_1,T_2,\dots,T_n\),每個串長度都是 \(m\),一個長度為 \(k\) 的有理數序列 \(p_1,p_2,\dots,p_k\) 保證 \(\sum p_i=1\)。每個字符串由前 \(k\) 個小寫字母構成。
我們進行下面的過程:

  1. 如果存在 \(j(1\le j\le n)\) 滿足 \(T_j\)\(S\) 的子串,那么停止這個過程。
  2. 否則按 \(p_i\) 的概率將第 \(i\) 個小寫字母加到 \(S\) 的末尾,然后繼續這個過程。

定義 \(f(S,T,p)\) 表示停止的時候 \(S\) 的期望長度。
給一個字符串 \(R\),對 \(R\) 的每個前綴,求出答案。也就是求出 \(f(R[1\dots i],T,p)\)\(i\in [1,|R|]\) 的所有值。
\(n\le 100,nm\le 10000,|R|\le 10^4\),答案對 \(1\ 000\ 000\ 007 取模\)

題解:

一個顯然的做法是建出 \(T_1,T_2,\cdots,T_n\) 的 AC 自動機,則題目相當於在 AC 自動機上隨機游走,問走到葉結點之一的期望次數。

\(E(x_i)\) 表示從 AC 自動機上第 \(i\) 個點出發,期望多少次能走到一個葉結點,列方程后高斯消元即得答案。未知數個數達到 \(O(nm)\),時間復雜度 \(O(n^3m^3)\),過不了。


考慮優化未知數個數。觀察方程 \(E(x_u)=1+\sum_{c=1}^k p_c E(x_{\operatorname{next}_{u,c}})\)

\(\operatorname{next}_{u,c}\) 表示從點 \(u\)\(c\) 的轉移邊到的結點)中,\(\operatorname{next}_{u,c}\) 要么是 Trie 樹上 \(u\) 的兒子,要么深度不超過 \(u\) 的深度。

考慮樹剖:對每個點 \(u\) 任選一個兒子 \(v\) 作為偏愛兒子進行樹鏈剖分。那這個方程就可以看作把 \(v\)\(u\) 的其他兒子和深度不超過 \(u\) 的深度的結點表示出來。

那么我們發現經過代入,每個結點的答案都可以通過一些鏈頂結點的答案來表示。怎么做呢?我們按從淺到深的順序來做。注意到對一個方程 \(E(x_u)=1+\sum_{c=1}^k p_c E(x_{\operatorname{next}_{u,c}})\),它所涉及到的最深層的結點是 \(u\) 的全部兒子,而它們除了偏愛兒子 \(v\) 以外全是鏈頂結點。而對於所涉及到的深度不超過 \(u\) 的深度的結點,由於我們是按從淺到深的順序,所以一定已經被表出,代入即可。

由於葉子結點不超過 \(n\) 個,所以剖出鏈的個數 \(O(n)\),未知數個數 \(O(n)\),總時間復雜度 \(O(n^3+n^2mk+|R|)\),可以通過。


此外這題還可以使用概率生成函數。

不熟悉概率生成函數的同學可以先做做 歌唱王國硬幣游戲

首先把輸入的 \(T_1,T_2,\cdots,T_n\) 拿去去重。

先考慮 \(S\) 初始為空的情況怎么做。

\(F_i(x)=\sum_{j\ge 0} f_{i,j}x^j,G(x)=\sum_{j\ge 0} g_jx^j\),其中 \(f_{i,j}\) 表示隨機第 \(j\) 次時恰好跟 \(T_i\) 匹配上的概率,\(g_j\) 表示隨機第 \(j\) 次時還沒有結束的概率。

根據概率生成函數的基礎知識,我們要求的是 \((\sum F_i)'(1)\)

由於 \(g_{j-1}-g_{j}=\sum_i f_{i,j}\),於是有 \(1+xG(x)=G(x)+\sum_i F_i(x)\)

此外我們根據 \(n\) 個串的信息還能列出 \(n\) 個方程。具體來說,若當前還沒有結束隨機過程,這時我們在串尾接上 \(T_i=T_{i,1}T_{i,2}\cdots T_{i,m}\) 后,隨機過程必然是已經結束了。然而也可能還沒有接完 \(T_i\) 就已經匹配完了。總之:\(G(x)\prod_{k=1}^m(p_{T_{i,k}}x)=\sum_{j=1}^n F_j(x)\sum_{l|T_i[1:l]=T_j[m-l+1:m]}\prod_{k=l+1}^m(p_{T_{i,k}}x)\)

我們最終要求 \((\sum F_i)'(1)\)。由第一個式子:

\((\sum F_i)(x)=1+(x-1)G(x)\)

\((\sum F_i)'(x)=G(x)+(x-1)G'(x)\)

\((\sum F_i)'(1)=G(1)\)

所以我們求的其實就是 \(G(1)\)

由后面的式子,\(G(1)\prod_{k=1}^mp_{T_{i,k}}=\sum_{j=1}^n F_j(1)\sum_{l|T_i[1:l]=T_j[m-l+1:m]}\prod_{k=m-l+1}^mp_{T_{j,k}}\)

此外還有 \(\sum_{j=1}^n F_j(1)=1\)

\(n+1\) 個方程 \(n+1\) 個未知數,可以解了。最后代入即得 \(G(1)\)

接下來是 \(S\) 初始不為空的情況,也就是我們給它欽定了一些前綴。

首先如果欽定的前綴里就包含了某個 \(T_i\),那就不用做了。

否則考慮照樣列方程。第一個方程是不變的。

第二個方程如何改變呢?關鍵在於,剛剛列方程時在串尾接上 \(T_i\) 的操作是在哪里都可以做的,如果使用原來的方程就變成了只有開始隨機之后才能接上。實際上還沒開始隨機的時候也可以往后面加 \(T_i\),而這樣對原函數方程的貢獻形如 \(\sum_{k}q_kx^k\)(除 \(x\) 以外都是常數),而代入 \(1\) 以后就徹徹底底變成常數了。

因此每次只有常數項有改變,不用每次都高斯消元,只要矩陣求逆后乘向量即可。

時間復雜度 \(O(n^3+n^2m+nmk+|R|)\)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM