日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

WHU 1572 Cyy and Fzz (AC自动机 dp )

發布時間:2023/12/15 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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 )的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。