BZOJ1444:[JSOI2009]有趣的游戏(AC自动机,矩阵乘法)

Description

Input

注意 是0<=P, n , l, m≤ 10.

Output

Sample Input

input 1
3 2 2
1 2
1 2
AB
BA
AA

input 2
3 4 2
1 2
1 2
AABA
ABAA
BAAA

Sample Output

output 1
0.25
0.50
0.25

output 2
0.31
0.33
0.37

HINT

Solution

一个很显然的想法就是我们模拟然后往死里跑,跑到天荒地老,总会跑到精度符合要求的时候┑( ̄Д  ̄)┍

写个矩乘优化一下多跑几遍就可以过了。

具体建立矩阵就是设$m[x][y]$表示$x$点转移到$y$点的概率。

如果$x$点是结束点,$m[x][y]=1$。否则就$m[x][son[x][i]]+=p[i]$,其中$i$是枚举的字母。

Code

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<queue>
 5 #define N (208)
 6 using namespace std;
 7 
 8 int n,m,l,tar[N];
 9 int sz,Son[N][12],Fail[N],End[N];
10 double x,y,p[N];
11 char s[N];
12 queue<int>q;
13 
14 struct Matrix
15 {
16     double m[N][N];
17     Matrix(){memset(m,0,sizeof(m));}
18 
19     Matrix operator * (const Matrix &b) const
20     {
21         Matrix c;
22         for (int i=0; i<=sz; ++i)
23             for (int j=0; j<=sz; ++j)
24                 for (int k=0; k<=sz; ++k)
25                     c.m[i][j]+=m[i][k]*b.m[k][j];
26         return c;
27     }
28 }A;
29 
30 void Insert(char s[],int id)
31 {
32     int now=0;
33     for (int i=0; i<l; ++i)
34     {
35         int c=s[i]-'A';
36         if (!Son[now][c]) Son[now][c]=++sz;
37         now=Son[now][c];
38     }
39     End[now]++; tar[id]=now;
40 }
41 
42 void Build_Fail()
43 {
44     for (int i=0; i<m; ++i)
45         if (Son[0][i]) q.push(Son[0][i]);
46     while (!q.empty())
47     {
48         int now=q.front(); q.pop();
49         for (int i=0; i<m; ++i)
50         {
51             if (!Son[now][i])
52             {
53                 Son[now][i]=Son[Fail[now]][i];
54                 continue;
55             }
56             Fail[Son[now][i]]=Son[Fail[now]][i];
57             q.push(Son[now][i]);
58         }
59     }
60 }
61 
62 void Solve()
63 {
64     for (int i=0; i<=sz; ++i)
65     {
66         if (End[i]) A.m[i][i]=1;
67         else for (int j=0; j<m; ++j) A.m[i][Son[i][j]]+=p[j];
68     }
69     for (int i=1; i<=50; ++i) A=A*A;
70     for (int i=1; i<=n; ++i)
71         printf("%.2lf\n",A.m[0][tar[i]]);
72 }
73 
74 int main()
75 {
76     scanf("%d%d%d",&n,&l,&m);
77     for (int i=0; i<m; ++i)
78         scanf("%lf%lf",&x,&y), p[i]=x/y;
79     for (int i=1; i<=n; ++i)
80         scanf("%s",s), Insert(s,i);
81     Build_Fail(); Solve();
82 }

 

posted @ 2018-11-28 17:46  Refun  阅读(175)  评论(0编辑  收藏  举报