tyvj P1519 博彩游戏(AC自动机+DP滚动数组)

P1519 博彩游戏

背景

Bob最近迷上了一个博彩游戏……

描述

这个游戏的规则是这样的:
每花一块钱可以得到一个随机数R,花上N块钱就可以得到一个随机序列;
有M个序列,如果某个序列是产生的随机序列的子串,那么就中奖了,否则不中。
Bob会告诉你这M个序列,和身上有的钱的总数N,当然还有R的范围。
请你告诉Bob中奖的概率有多少?

输入格式

第一行三个用空格隔开的数N、M和R的范围R。
其中1<=R<=9,0<N<=60,0<M<=20000。
下面M行每行一个字符串(长度小于等于20),字符串的每一位范围在1-r之间
保证必要运算都在64位整型范围内。

输出格式

一行一个实数,表示中奖的概率(保留小数点后5位小数)。

测试样例1

输入

5 1 3 
1

输出

0.86831

备注

数据分布:
第1个点~第10个点,每个点5分;
第11个点~第15个点,每个点10分。

对于样例的解释:
随机序列一共有3^5=243个,其中包含"1"的个数为211个,则概率为211/243=0.86831Bob HAN

【思路】

      

   AC自动机+DP。

       与bzoj1030一样思路都是要转化为求AC自动机上不经过单词节点的方案。不同的是这个题需要用滚动数组不然MLE <_<

       尼玛tyvj上double要用%f,让我WA了千万发,我说以前怎么提交不过WTF

【代码】

 1 #include<set>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<cstring>
 5 #include<iostream>
 6 using namespace std;
 7 typedef long long LL;
 8 const int N=20000+5,L=20+5;
 9 const int node = N*L;
10 const int sigma = 10;
11 
12 char s[L]; int n,m,r; LL d[2][node];
13 
14 struct ACauto{
15     int ch[node][sigma],f[node],val[node],sz;
16     void clear() {
17         sz=1; memset(ch[0],0,sizeof(ch[0]));
18     }
19     void insert(char *s) {
20         int n=strlen(s),u=0;
21         for(int i=0;i<n;i++) {
22             int c=s[i]-'1';
23             if(!ch[u][c]) {
24                 memset(ch[sz],0,sizeof(ch[sz]));
25                 val[sz]=0; ch[u][c]=sz++;
26             }
27             u=ch[u][c];
28         }
29         val[u]=1;
30     }
31     void get_Fail() {
32         queue<int> q;
33         f[0]=0;
34         for(int c=0;c<r;c++) 
35             if(ch[0][c]) f[ch[0][c]]=0,q.push(ch[0][c]);
36         while(!q.empty()) {
37             int qr=q.front(); q.pop();
38             for(int c=0;c<r;c++) {
39                 int u=ch[qr][c]; if(!u) continue;
40                 q.push(u);  int v=f[qr];
41                 while(v&&!ch[v][c]) v=f[v];
42                 if(val[ch[v][c]]) val[u]=1;
43                 f[u]=ch[v][c];
44             }
45         }
46      }
47 }ac;
48 int que[2][N],cnt[2];
49 int main() {
50     //freopen("in.in","r",stdin);
51     //freopen("out.out","w",stdout);
52     scanf("%d%d%d",&m,&n,&r);
53     ac.clear();
54     for(int i=0;i<n;i++) {
55         scanf("%s",s); ac.insert(s);
56     }
57     ac.get_Fail();
58     d[0][0]=1;
59     int x=0;
60     for(int i=1;i<=m;i++) {
61         x^=1;
62         memset(d[x],0,sizeof(d[x]));
63         for(int j=0;j<ac.sz;j++) if(!ac.val[j]&&d[x^1][j]) {
64             for(int c=0;c<r;c++) {
65                 int k=j; while(!ac.ch[k][c]&&k) k=ac.f[k];
66                 d[x][ac.ch[k][c]]=d[x^1][j]+d[x][ac.ch[k][c]];
67             }
68         }
69     }
70     LL ans1=0,ans2=1;
71     for(int i=1;i<=m;i++) ans2*=(LL)r;
72     for(int i=0;i<ac.sz;i++)
73         if(!ac.val[i]) ans1+=d[x][i];
74     double f=((double)ans2-(double)ans1)/(double)ans2;
75     printf("%.5f
",f);
76     return 0;
77 }
原文地址:https://www.cnblogs.com/lidaxin/p/5196335.html