Bzoj1444 [Jsoi2009]有趣的游戏

 

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 1075  Solved: 367

Description

Input

注意 是0<=P

Output

Sample Input


Sample Output


HINT

 

 30%的数据保证, n ≤ 2. 50%的数据保证, n ≤ 5. 100%的数据保证, n , l, m≤ 10.

 

Source

 

概率

AC自动机+矩阵乘法

 

先建好AC自动机,得到不同字母间的转移关系。

对于每个结点,如果它是某个玩家的字符串末,则它转移到自己的概率为1,否则按照读入的概率转移到不同的字母去。

↑以此构建转移矩阵。

精度要求1-e2,那么尝试矩阵暴力自乘,使得概率趋于稳定。自乘30次精度不够,会WA,40次就过了。

 

  1 /*by SilverN*/
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 #include<queue>
  8 using namespace std;
  9 const int mxn=50;
 10 int n,l,m;
 11 struct Aca{
 12     int t[300][12];
 13     int fail[300],end[300];
 14     int pos[300];
 15     int cnt,rt,id;
 16     void clear(){
 17         cnt=0;memset(t,0,sizeof t);memset(fail,0,sizeof fail);
 18         rt=++cnt;id=0;
 19         return;
 20     }
 21     void insert(char s[]){
 22         int len=strlen(s);
 23         int now=rt;
 24         for(int i=0;i<len;i++){
 25             if(!t[now][s[i]-'A'])
 26                 t[now][s[i]-'A']=++cnt;
 27             now=t[now][s[i]-'A'];
 28         }
 29         end[now]++;
 30         pos[++id]=now;//记录每个串末尾的结点编号 
 31         return;
 32     }
 33     void Build(){
 34         queue<int>q;
 35         int i,j;
 36         for(i=0;i<m;i++){
 37             if(t[rt][i]){
 38                 q.push(t[rt][i]);
 39                 fail[t[rt][i]]=rt;
 40             }
 41             else t[rt][i]=rt;
 42         }
 43         while(!q.empty()){
 44             int u=q.front();q.pop();
 45             for(i=0;i<m;i++){
 46                 if(t[u][i]){
 47                     q.push(t[u][i]);
 48                     fail[t[u][i]]=t[fail[u]][i];
 49                 }
 50                 else t[u][i]=t[fail[u]][i];
 51             }
 52         }
 53     }
 54 };
 55 Aca a;//AC自动机 
 56 //
 57 struct Matrix{
 58     double c[130][130];
 59     int x;
 60     void clear(){memset(c,0,sizeof c);x=0;return;}
 61     friend Matrix operator * (Matrix a,Matrix b){
 62         Matrix res;
 63         res.clear();
 64         res.x=a.x;
 65         for(int i=1;i<=a.x;i++){
 66             for(int j=1;j<=a.x;j++){
 67                 for(int k=1;k<=a.x;k++){
 68                     res.c[i][j]+=a.c[i][k]*b.c[k][j];
 69                 }
 70             }
 71         }
 72         return res;
 73     }
 74 }mp;//矩阵乘 
 75 char s[mxn];
 76 double p[mxn];
 77 int main(){
 78     int i,j,P,Q;
 79     scanf("%d%d%d",&n,&l,&m);
 80     for(i=1;i<=m;i++){
 81         scanf("%d%d",&P,&Q);
 82         p[i]=(double)P/Q;
 83     }
 84     a.clear();
 85     for(i=1;i<=n;i++){
 86         scanf("%s",s);
 87         a.insert(s);
 88     }
 89     a.Build();
 90     for(i=1;i<=a.cnt;i++){//统计概率 
 91         if(a.end[i]) mp.c[i][i]=1;
 92         else for(j=0;j<m;j++){
 93             mp.c[i][a.t[i][j]]+=p[j+1];
 94         }
 95     }
 96 /*
 97     for(i=1;i<=a.cnt;i++){
 98         for(j=1;j<=a.cnt;j++){
 99             printf("%.3f ",mp.c[i][j]);
100         }
101         printf("\n");
102     }
103 */    
104     mp.x=a.cnt;
105     for(i=1;i<=40;i++)
106         mp=mp*mp;
107     for(i=1;i<=n;i++)
108         printf("%.2f\n",mp.c[1][a.pos[i]]);
109     return 0;
110 }
111 /*
112 3 2 2
113 1 2
114 1 2
115 AB
116 BA
117 AA
118 */

 

posted @ 2017-01-23 22:15  SilverNebula  阅读(518)  评论(0编辑  收藏  举报
AmazingCounters.com