bzoj1444[Jsoi2009]有趣的遊戲[AC自動機]
阿新 • • 發佈:2019-04-11
cstring () pro end names bzoj 學習 http cpp
題面
bzoj
我要向師父學習善待每一只數據結構
考慮成環,那麽高斯消元
然鵝這道題太小了 所以直接轉移矩陣自乘就好啦
終點不向外連邊 有一條向自己的,概率為一的自環來作為結尾
對於其他店 若有邊\((u -> v) = p\) 那麽mat[u][v] += p
#include <cmath> #include <cstring> #include <cstdio> #include <cstdlib> #include <algorithm> #include <complex> #include <ctime> #include <vector> #include <queue> #include <bitset> #define mp(x, y) make_pair(x, y) using namespace std; const int N = 15; const int M = 105; int n, m, len, sz, en[N]; double p[N]; struct Matrix{ double w[M][M]; void clear(){ for(int i = 0; i <= sz; ++i) for(int j = 0; j <= sz; ++j) w[i][j] = 0; } void print(){ printf("--------------------\n"); for(int i = 0; i <= sz; ++i){ for(int j = 0; j <= sz; ++j) printf("%.2lf ", w[i][j]); printf("\n"); } printf("--------------------\n"); } friend Matrix operator *(const Matrix x, const Matrix y){ Matrix z; z.clear(); for(int i = 0; i <= sz; ++i) for(int j = 0; j <= sz; ++j) for(int k = 0; k <= sz; ++k) z.w[i][j] += x.w[i][k] * y.w[k][j]; // z.print(); return z; } }mat, res; struct AC{ int ch[M][N], f[M]; bool flag[M]; queue<int> que; void ins(char* str, int id){ int now = 0; for(int i = 1, cc; i <= len; ++i){ cc = str[i] - 'A'; if(!ch[now][cc]) ch[now][cc] = ++sz; now = ch[now][cc]; } en[id] = now, flag[now] = 1; } void build(){ int now = 0; for(int i = 0; i < m; ++i) if(ch[0][i]) que.push(ch[0][i]); while(!que.empty()){ int fro = que.front(); que.pop(); for(int i = 0; i < m; ++i){ if(ch[fro][i]) f[ch[fro][i]] = ch[f[fro]][i], que.push(ch[fro][i]);//!! else ch[fro][i] = ch[f[fro]][i]; } } mat.clear(); for(int i = 0; i <= sz; ++i){ if(flag[i]){ mat.w[i][i] = 1; continue; } for(int j = 0; j < m; ++j){ mat.w[i][ch[i][j]] += p[j]; } } } }ac; int main(){ scanf("%d%d%d", &n, &len, &m); for(int i = 0; i < m; ++i){ double x, y; scanf("%lf%lf", &x, &y); p[i] = x / y; } char str[N]; for(int i = 1; i <= n; ++i){ scanf("%s", str + 1); ac.ins(str, i); } ac.build(); for(int i = 1; i <= 100; ++i) mat = mat * mat; //轉移矩陣自乘 得到來自0的解 for(int i = 1; i <= n; ++i) printf("%.2lf\n", mat.w[0][en[i]]); return 0; }
bzoj1444[Jsoi2009]有趣的遊戲[AC自動機]