zoukankan      html  css  js  c++  java
  • bzoj 1444 AC自动机 + 矩阵乘法 | 高斯消元

    恶补了一下AC自动机,花了一天时间终于全部搞明白了。

    思路:将每个人的串加入AC自动机,在AC自动机生成的状态图上建边,注意单词末尾的节点只能转移到自己概率为1,

    然后将矩阵自乘几十次后误差就很小了, 或者可以高斯消元搞出精确解。

    #include<bits/stdc++.h>
    #define LL long long
    #define ll long long
    #define fi first
    #define se second
    #define mk make_pair
    #define pii pair<int, int>
    #define y1 skldjfskldjg
    #define y2 skldfjsklejg
    
    using namespace std;
    
    const int N = 100 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    
    int n, l, m, pos[11];
    double pro[11];
    char s[11];
    
    struct Matrix {
        int r, c;
        double a[101][101];
        Matrix(int r = 0, int c = 0) {
            this->r = r;
            this->c = c;
            memset(a, 0, sizeof(a));
        }
    
        Matrix operator * (const Matrix &B) const {
            Matrix C(r, c);
            for(int i = 0; i < r; i++)
                for(int j = 0; j < c; j++)
                    for(int k = 0; k < r; k++)
                        C.a[i][j] += a[i][k] * B.a[k][j];
            return C;
        }
    };
    
    struct Ac {
        int val[N], ch[N][26], f[N], last[N], cnt, SZ;
    
        void init(int SZ = 26) {
            cnt = 0; this->SZ = SZ;
            for(int c = 0; c < SZ; c++) ch[0][c] = 0;
        }
    
        int getId(char c) {
            return c - 'A';
        }
    
        int newNode() {
            cnt++;
            memset(ch[cnt], 0, sizeof(ch[cnt]));
            val[cnt] = f[cnt] = last[cnt] = 0;
            return cnt;
        }
    
        void add(char *s, int &pos) {
            int u = 0;
            for(int i = 0; s[i]; i++) {
                int c = getId(s[i]);
                if(!ch[u][c]) ch[u][c] = newNode();
                u = ch[u][c];
            }
            val[u]++;
            pos = u;
        }
    
        void build() {
            queue<int> que;
            f[0] = 0;
            for(int c = 0; c < SZ; c++) {
                if(!ch[0][c]) continue;
                f[ch[0][c]] = last[ch[0][c]] = 0;
                que.push(ch[0][c]);
            }
            while(!que.empty()) {
                int u = que.front(); que.pop();
                for(int c = 0; c < SZ; c++) {
                    int v = ch[u][c];
                    if(!v) {
                        ch[u][c] = ch[f[u]][c];
                        continue;
                    } else {
                        que.push(v);
                        f[v] = ch[f[u]][c];
                        last[v] = val[f[v]] ? f[v] : last[f[v]];
                    }
                }
            }
        }
    
        void buildMatrix(Matrix &A) {
            for(int u = 0; u <= cnt; u++) {
                if(val[u]) A.a[u][u] = 1;
                else {
                    for(int c = 0; c < m; c++) {
                        int v = ch[u][c];
                        A.a[u][v] += pro[c];
                    }
                }
            }
        }
    } ac;
    
    int main() {
        scanf("%d%d%d", &n, &l, &m);
        for(int i = 0; i < m; i++) {
            double p, q;
            scanf("%lf%lf", &p, &q);
            pro[i] = p / q;
        }
    
        ac.init(m);
    
        for(int i = 1; i <= n; i++) {
            scanf("%s", s);
            ac.add(s, pos[i]);
        }
    
        ac.build();
        Matrix A(ac.cnt + 1, ac.cnt + 1);
        ac.buildMatrix(A);
    
        for(int i = 1; i <= 40; i++)
            A = A * A;
    
        for(int i = 1; i <= n; i++) printf("%.2f
    ", A.a[0][pos[i]]);
        return 0;
    }
    
    
    /*
    */
  • 相关阅读:
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    AcWing 1049. 大盗阿福 状态机模型dp
    AcWing 11. 背包问题求方案数
    AcWing 10. 有依赖的背包问题
    AcWing 7. 混合背包问题
    AcWing 532. 货币系统
    2018-2019 ACM-ICPC, Asia East Continent Final L Eventual … Journey
    AcWing 487. 金明的预算方案
  • 原文地址:https://www.cnblogs.com/CJLHY/p/9465075.html
Copyright © 2011-2022 走看看