题目链接:http://vjudge.net/contest/142513#problem/A
题意:给出一些字符和各自对应的选择概率,随机选择L次后将得到一个长度为L的随机字符串S.给出K个模版串,计算S不包含任何一个串的概率.
分析:
在构造好的AC自动机里面,每随机生成一个字母,相当于在AC自动机中随机走一步。所有单词结点标记为禁止,本题就是从结点 0 走 l 步,不进入任何禁止结点的概率。
#include <bits/stdc++.h> using namespace std;const int SIGMA_SIZE = 64; const int MAXNODE = 500;int idx[256]; char s[30][30]; double prob[SIGMA_SIZE]; int n;struct AhoCorasickAutomata {int ch[MAXNODE][SIGMA_SIZE];int f[MAXNODE];int match[MAXNODE];int sz;void init(){sz = 1;memset(ch[0],0,sizeof(ch[0]));}void insert(char *s){int u = 0,n = strlen(s);for(int i=0; i<n; i++){int c = idx[s[i]];if(!ch[u][c]){memset(ch[sz],0,sizeof(ch[sz]));match[sz] = 0;ch[u][c] = sz++;}u = ch[u][c];}match[u] = 1;}void getFail(){queue<int> q;f[0] = 0;for(int c=0; c<SIGMA_SIZE; c++){int u = ch[0][c];if(u){f[u] = 0;q.push(u);}}while(!q.empty()){int r = q.front();q.pop();for(int c=0; c<SIGMA_SIZE; c++){int u = ch[r][c];if(!u){ch[r][c]=ch[f[r]][c];continue;}q.push(u);int v = f[r];while(v&&!ch[v][c])v = f[v];f[u] = ch[v][c];match[u] |=match[f[u]];}}} };AhoCorasickAutomata ac;double d[MAXNODE][105]; int vis[MAXNODE][105];double getProb(int u,int l) {if(!l) return 1.0;if(vis[u][l]) return d[u][l];vis[u][l] = 1;double& ans = d[u][l];ans = 0.0;for(int i=0; i<n; i++){if(!ac.match[ac.ch[u][i]])ans += prob[i]*getProb(ac.ch[u][i],l-1);}return ans; }int main() {int T;scanf("%d",&T);for(int kase = 1; kase<=T; kase ++){int k,l;scanf("%d",&k);for(int i=0; i<k; i++)scanf("%s",s[i]);scanf("%d",&n);for(int i=0; i<n; i++){char ch[9];scanf("%s%lf",ch,&prob[i]);idx[ch[0]] = i;}ac.init();for(int i=0; i<k; i++)ac.insert(s[i]);ac.getFail();scanf("%d",&l);memset(vis,0,sizeof(vis));printf("Case #%d: %.6lf\n",kase,getProb(0,l));}return 0; }