BZOJ 1444: [Jsoi2009]有趣的游戏 [AC自动机 高斯消元]
2017-04-04 22:14
543 查看
1444: [Jsoi2009]有趣的游戏
题意:每种字母出现概率\(p_i\),有一些长度len的字符串,求他们出现的概率套路DP的话,\(f[i][j]\) i个字符走到节点j的概率,建出转移矩阵来矩乘几十次可以认为是无穷个字符,就得到概率了
但我们发现Trie图也是图啊,直接高斯消元就好了,\(f[i]\)表示走到节点i的期望次数
注意\(f[0]\)需要+1
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; typedef long long ll; const int N=105; const double eps=1e-8; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int n, len, m, pos ; double p , x, y; char s ; namespace ac{ struct meow{int ch[11], fail, val;} t ; int sz; void insert(char *s, int id) { int u=0; for(int i=1; i<=len; i++) { int c=s[i]-'A'; if(!t[u].ch[c]) t[u].ch[c] = ++sz; u=t[u].ch[c]; } t[u].val=1; pos[id]=u; } int q , head, tail; void build() { head=tail=1; for(int i=0; i<m; i++) if(t[0].ch[i]) q[tail++] = t[0].ch[i]; while(head!=tail) { int u=q[head++]; t[u].val |= t[t[u].fail].val; for(int i=0; i<m; i++) { int &v = t[u].ch[i]; if(!v) v = t[t[u].fail].ch[i]; else t[v].fail = t[t[u].fail].ch[i], q[tail++]=v; } } } }using ac::t; using ac::sz; double a ; namespace eq{ void build() { a[0][sz+1] = 1; for(int i=0; i<=sz; i++) { //printf("i %d\n",i); a[i][i]=1; if(!t[i].val) for(int j=0; j<m; j++) a[ t[i].ch[j] ][i] -= p[j];// printf("ch %d %lf %d\n",j,p[j],t[i].ch[j]); } //for(int i=0; i<=n; i++) for(int j=0; j<=n+1; j++) printf("%lf%c",a[i][j],j==n+1?'\n':' '); } void gauss(int n) { for(int i=0; i<=n; i++) { int r=i; for(int j=i; j<=n; j++) if(abs(a[j][i])>abs(a[r][i])) r=j; if(r!=i) for(int j=0; j<=n+1; j++) swap(a[r][j], a[i][j]); for(int k=i+1; k<=n; k++) { double t = a[k][i]/a[i][i]; for(int j=i; j<=n+1; j++) a[k][j] -= t*a[i][j]; } } for(int i=n; i>=0; i--) { for(int j=n; j>i; j--) a[i][n+1] -= a[i][j]*a[j][n+1]; a[i][n+1] /= a[i][i]; } } } int main() { freopen("in","r",stdin); n=read(); len=read(); m=read(); int flag=0; for(int i=0; i<m; i++) x=read(), y=read(), p[i]=(double)x/y, flag |= p[i]>eps; if(!flag) {for(int i=1; i<=n; i++) puts("0.00"); return 0;} for(int i=1; i<=n; i++) scanf("%s",s+1), ac::insert(s, i); ac::build(); eq::build(); eq::gauss(sz); //for(int i=1; i<=n; i++) printf("%d ",pos[i]); puts(" pos"); for(int i=1; i<=n; i++) printf("%.2lf\n", a[pos[i]][sz+1]); }
相关文章推荐
- bzoj1444 [Jsoi2009]有趣的游戏(期望概率+AC自动机+高斯消元)
- [AC自动机 概率DP 矩阵乘法||高斯消元] BZOJ 1444 [Jsoi2009]有趣的游戏
- BZOJ1444:[Jsoi2009]有趣的游戏 (AC自动机+概率DP+高斯消元)
- bzoj 1444: [Jsoi2009]有趣的游戏【AC自动机+dp+高斯消元】
- BZOJ:4820: [Sdoi2017]硬币游戏&&BZOJ:1444: [Jsoi2009]有趣的游戏(高斯消元求概率)
- BZOJ 1444: [Jsoi2009]有趣的游戏 AC自动机加矩阵快速幂
- BZOJ 1444 [Jsoi2009]有趣的游戏 (AC自动机 + 概率DP + Gauss)
- bzoj1444: [Jsoi2009]有趣的游戏
- BZOJ1444: [Jsoi2009]有趣的游戏 矩阵求逆+AC自动机
- BZOJ 1444 JSOI2009 有趣的游戏 AC自动机+矩阵乘法
- 【bzoj1444】[Jsoi2009]有趣的游戏
- bzoj1444 [Jsoi2009]有趣的游戏
- 【bzoj1444】[Jsoi2009]有趣的游戏 AC自动机+矩阵乘法
- BZOJ 1444: [Jsoi2009]有趣的游戏
- Bzoj1444 [Jsoi2009]有趣的游戏
- BZOJ1444 : [Jsoi2009]有趣的游戏
- 【BZOJ1444】[Jsoi2009]有趣的游戏 AC自动机+概率DP+矩阵乘法
- 【 bzoj 1444 】 [Jsoi2009]有趣的游戏 - AC自动机+矩阵乘法
- BZOJ 1444 [Jsoi2009] 有趣的游戏
- bzoj 1444 [Jsoi2009]有趣的游戏