WHU 1572 Cyy and Fzz (AC自动机 dp )
生活随笔
收集整理的這篇文章主要介紹了
WHU 1572 Cyy and Fzz (AC自动机 dp )
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
? ? ?給出n個串,求任意長度為m的字符串包含串的個數的期望。(n<=8,m<=14,給定串的長度不超過12)。
?
?
Solution:
? ? ?首先可以想到應該用概率DP,我們需要至少3維,dp[i][j][k]表示第i個數字為j,已經包含了k個串的概率.
? ? ?然后,問題是找到狀態轉移的方法
? ? ?由于是字符串相關,AC自動機應該是第一個想到的.
? ? ?然后注意到,對于k個串的k,直接求并不好維護,也沒辦法判斷重復的 .由于只有8個串,自然就想到用更簡單的方法,用狀態壓縮來存已經包含了哪些串.
? ? ?在建trie圖的時候,要注意一個結點的狀態應該是包含了它的fail節點的狀態的.
? ? ?從u到v的轉移
? ? ? ? ? ? ? ? ?dp[i+1][u][sta[u]|sta[v]]+=dp[i][v][sta[v]]
?
#include <iostream> #include <queue> #include <cstdio> #include <string> #include <cstring> using namespace std; const int SD = 26; const int MAXL = 1000; struct Tire {int next[MAXL][SD], fail[MAXL], eofs[MAXL];int Root, cnt;int newnode() {for (int i = 0; i < SD; i++) next[cnt][i] = -1;eofs[cnt++] = 0;return cnt - 1;}void init() {cnt = 0;Root = newnode();}void Ins (char buf[], int k) {int len = strlen (buf);int now = Root;for (int i = 0; i < len; i++) {if (next[now][buf[i] - 'a'] == -1)next[now][buf[i] - 'a'] = newnode();now = next[now][buf[i] - 'a'];}eofs[now] |= (1 << k);}void build() {queue<int> ql;fail[Root] = Root;for (int i = 0; i < SD; i++) {if (next[Root][i] == -1)next[Root][i] = Root;else {fail[next[Root][i]] = Root;ql.push (next[Root][i]);}}while (!ql.empty() ) {int now = ql.front(); ql.pop();eofs[now] |= eofs[fail[now]];for (int i = 0; i < SD; i++)if (next[now][i] == -1) {next[now][i] = next[fail[now]][i];}else {fail[next[now][i]] = next[fail[now]][i];ql.push (next[now][i]);}}} } AC; int Cs, n, m; char s[20]; double dp[20][400][1 << 9], tmp = 1. / 26; int main() {scanf ("%d", &Cs);while (Cs--) {memset (dp, 0, sizeof dp);AC.init();scanf ("%d %d", &n, &m);for (int i = 0; i < n; i++) {scanf ("%s", s);AC.Ins (s, i);}AC.build();dp[0][0][0] = 1;for (int i = 0; i < m; i++)for (int u = 0; u < AC.cnt; u++)for (int st = 0; st < (1 << n); st++)if (dp[i][u][st] > 0)for (int j = 0; j < SD; j++) {int v = AC.next[u][j];dp[i + 1][v][st | AC.eofs[v]] += dp[i][u][st] * tmp;}double ans = 0;for (int i = 0; i < AC.cnt; i++)for (int st = 0; st < (1 << n); st++)if (dp[m][i][st] > 0) {int sum = 0;for (int k = 0; k < n; k++)if (st & (1 << k) ) sum++;ans += dp[m][i][st] * sum;}printf ("%.6f\n", ans);} } View Code?
轉載于:https://www.cnblogs.com/keam37/p/4442799.html
總結
以上是生活随笔為你收集整理的WHU 1572 Cyy and Fzz (AC自动机 dp )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 研究生项目狗自救指南
- 下一篇: c语言英文分词,英文分词的算法和原理