【bzoj1444】[Jsoi2009]有趣的游戏
1444: [Jsoi2009]有趣的游戏
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1007 Solved: 334
[Submit][Status][Discuss]
Description
Input
注意 是0<=P
Output
Sample Input
Sample Output
【题解】
AC自动机+矩阵乘法
首先把模式串建成AC自动机,构建出转移矩阵。
构造方法:a[i][j]表示从第i个结点转移到第j个结点的概率,则如果j被标记过,f[i][j]=1,否则f[i][j]=possble[ch[j]]
具体见代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<ctime> 6 #include<cmath> 7 #include<algorithm> 8 using namespace std; 9 #define MAXN 510 10 struct node{double p[MAXN][MAXN]; node(){memset(p,0,sizeof(p));}}a; 11 int n,l,m,cnt,id,fail[MAXN],end[MAXN],pos[MAXN],q[MAXN],tr[MAXN][27]; 12 double chty[MAXN]; 13 char ch[MAXN]; 14 inline int read() 15 { 16 int x=0,f=1; char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} 19 return x*f; 20 } 21 void insert() 22 { 23 int now=0; 24 for(int i=1;i<=l;i++) 25 { 26 if(!tr[now][ch[i]-'A']) tr[now][ch[i]-'A']=++cnt; 27 now=tr[now][ch[i]-'A']; 28 } 29 end[now]=1; pos[++id]=now; 30 } 31 void build() 32 { 33 int head=0,tail=0; 34 for(int i=0;i<m;i++) if(tr[0][i]) q[++tail]=tr[0][i]; 35 while(++head<=tail) 36 { 37 int x=q[head]; end[x]|=end[fail[x]]; 38 for(int i=0;i<m;i++) 39 { 40 if(!tr[x][i]) tr[x][i]=tr[fail[x]][i]; 41 else {fail[tr[x][i]]=tr[fail[x]][i]; q[++tail]=tr[x][i];} 42 } 43 } 44 } 45 void get() 46 { 47 for(int i=0;i<=cnt;i++) 48 { 49 if(end[i]) a.p[i][i]=1; 50 else for(int x=0;x<m;x++) a.p[i][tr[i][x]]+=chty[x]; 51 } 52 } 53 inline node operator *(node &x,node &y) 54 { 55 node z; 56 for(int i=0;i<=cnt;i++) 57 for(int j=0;j<=cnt;j++) 58 for(int k=0;k<=cnt;k++) 59 z.p[i][j]+=x.p[i][k]*y.p[k][j]; 60 return z; 61 } 62 int main() 63 { 64 //freopen("cin.in","r",stdin); 65 //freopen("cout.out","w",stdout); 66 n=read(); l=read(); m=read(); 67 for(int i=0;i<m;i++) chty[i]=(double)read()/read(); 68 for(int i=1;i<=n;i++) {scanf("%s",ch+1); insert();} 69 build(); 70 get(); 71 for(int i=1;i<=50;i++) a=a*a; 72 for(int i=1;i<=n;i++) printf("%.2lf\n",(double)a.p[0][pos[i]]); 73 return 0; 74 }