BZOJ 1444: [Jsoi2009]有趣的游戏
1444: [Jsoi2009]有趣的游戏
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1126 Solved: 394
[Submit][Status][Discuss]
Description
Input
注意 是0<=P
Output
Sample Input
Sample Output
HINT
30%的数据保证, n ≤ 2. 50%的数据保证, n ≤ 5. 100%的数据保证, n , l, m≤ 10.
Source
分析:
就是建出Trie图然后构造转移方程高斯消元一发...
然后我好像之前写的AC自动机的构建有些问题,并没有根节点向根节点转移的边,所以貌似出了一些问题...
代码:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> //by NeighThorn using namespace std; const int maxn=10+5,maxm=maxn*maxn+5; int n,l,m,tot,head,tail,q[maxm],id[maxn],vis[maxn]; double t[maxn],a[maxm][maxm]; char s[maxn]; struct Trie{ int cnt,fail,nxt[26]; }tr[maxm]; inline int insert(char *s){ int p=0; for(int i=0;i<l;i++){ if(!tr[p].nxt[s[i]-'A']) tr[p].nxt[s[i]-'A']=++tot; p=tr[p].nxt[s[i]-'A']; } tr[p].cnt++; return p; } inline void buildACM(void){ head=tail=0,q[0]=0; while(head<=tail){ int top=q[head++]; for(int i=0;i<m;i++){ int p=tr[tr[top].fail].nxt[i]; if(!tr[top].nxt[i]) tr[top].nxt[i]=p; else{ if(top) tr[tr[top].nxt[i]].fail=p; q[++tail]=tr[top].nxt[i]; } } } } inline void gauss(void){ for(int i=0;i<=tot;i++){ int k=i; while(!fabs(a[k][i])&&k<tot) k++; if(k!=i) for(int j=0;j<=tot+1;j++) swap(a[k][j],a[i][j]); for(int l=0;l<=tot;l++) if(l!=i&&fabs(a[l][i])){ double lala=a[l][i]/a[i][i]; for(int s=0;s<=tot+1;s++) a[l][s]-=lala*a[i][s]; } } } signed main(void){ scanf("%d%d%d",&n,&l,&m); for(int i=1,x,y;i<=m;i++){ scanf("%d%d",&x,&y),t[i-1]=1.0*x/(double)y; if(t[i-1]==0.0) vis[i-1]=1; } for(int i=1,flag;i<=n;i++){ scanf("%s",s);flag=0; for(int j=0;j<l&&!flag;j++) flag|=vis[s[j]-'A']; if(flag) id[i]=-1; else id[i]=insert(s); } buildACM();a[0][tot+1]=1.0; for(int i=0;i<=tot;i++){ a[i][i]+=1.0; if(!tr[i].cnt) for(int j=0;j<m;j++) a[tr[i].nxt[j]][i]+=-1.0*t[j]; } gauss(); for(int i=1;i<=n;i++){ if(id[i]==-1) puts("0.00"); else printf("%.2f\n",a[id[i]][tot+1]/a[id[i]][id[i]]); } return 0; }
By NeighThorn