bzoj1444 有趣的游戏(AC自动机+矩阵乘法)

多串比较,又和概率相关,一定是AC自动机维护概率dp

但会发现dp转移顺序一言难尽。。。

于是考虑把方程放到矩阵中高斯消元

但你又会发现,有个偷懒的做法,就是把得到的矩阵自乘,乘上很多次便可无限接近答案

数据小,不卡精,水果。。。

 1 #include<queue>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int n,m,len,cnt,tot;
 7 char s[15];
 8 int pos[15];
 9 bool ed[105];
10 double p[15];
11 struct Trie{
12     int son[10];
13     int fail;
14 }tr[105];
15 struct node{
16     double f[105][105];
17 }ans;
18 void build(char a[],int mrk){
19     int now=0;
20     for(int i=1;i<=len;i++){
21         int k=a[i]-'A';
22         if(!tr[now].son[k])tr[now].son[k]=++tot;
23         now=tr[now].son[k];
24     }
25     ed[now]=true;
26     pos[mrk]=now;
27 }
28 void getfail(){
29     queue<int>que;
30     for(int i=0;i<10;i++){
31         if(tr[0].son[i])que.push(tr[0].son[i]);
32     }
33     while(!que.empty()){
34         int u=que.front();
35         que.pop();
36         for(int i=0;i<10;i++){
37             if(tr[u].son[i]){
38                 tr[tr[u].son[i]].fail=tr[tr[u].fail].son[i];
39                 que.push(tr[u].son[i]);
40             }
41             else tr[u].son[i]=tr[tr[u].fail].son[i];
42         }
43     }
44 }
45 void get_squ(){
46     for(int i=0;i<=tot;i++){
47         if(ed[i]){
48             ans.f[i][i]=1;
49             continue;
50         }
51         for(int j=0;j<10;j++){
52             ans.f[i][tr[i].son[j]]+=p[j];
53         }
54     }
55 }
56 void mul(){
57     node c;
58     for(int i=0;i<=tot;i++){
59         for(int j=0;j<=tot;j++){
60             c.f[i][j]=0.00;
61         }
62     }
63     for(int i=0;i<=tot;i++){
64         for(int j=0;j<=tot;j++){
65             for(int k=0;k<=tot;k++){
66                 c.f[i][j]+=ans.f[i][k]*ans.f[k][j];
67             }
68         }
69     }
70     for(int i=0;i<=tot;i++){
71         for(int j=0;j<=tot;j++){
72             ans.f[i][j]=c.f[i][j];
73         }
74     }
75 }
76 int main(){
77     scanf("%d%d%d",&n,&len,&m);
78     for(int i=1;i<=m;i++){
79         int x,y;
80         scanf("%d%d",&x,&y);
81         p[i-1]=(double)x/(double)y;
82     }
83     for(int i=1;i<=n;i++){
84         scanf("%s",s+1);
85         build(s,i);
86     }
87     getfail();get_squ();
88     for(int i=1;i<=50;i++)mul();
89     for(int i=1;i<=n;i++){
90         printf("%.2lf\n",ans.f[0][pos[i]]);
91     }
92     return 0;
93 }

 

posted @ 2018-11-25 16:06  Mr_Handsome  阅读(186)  评论(0编辑  收藏  举报