zoukankan      html  css  js  c++  java
  • [日常摸鱼]bzoj1444 [JSOI2009]有趣的游戏——AC自动机+矩阵

    今天学校跳蚤市场摆摊聚众吸毒打call,东西卖了一百多好开心_(:з」∠)_

    (然后大家中午就去吃了一顿好的x) 下午听演讲然后现在来填坑orz(其实是昨晚的坑)

    题目:bzoj1444

    先用字符串构造一个AC自动机,对于一个节点$k$来说,转移到$tr[k][i]$的概率是$p[i]$,根据概率构造出转移矩阵,如果一个点是模式串的结尾就自己给自己连一条1,发现一些点之间会相互影响,那么把转移矩阵乘几十次就可以了…

    (这好像是个马尔科夫链的模型?

    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    
    const int N=105;
    const int S=26;
    struct matrix
    {
        double m[N][N];
        matrix(){memset(m,0,sizeof(m));}
    };
    
    int n,m,l,cnt;
    int tr[N][S+3],fail[N],pos[N];
    bool danger[N];
    double pro[S+3],p,q;
    char s[N];
    queue<int>Q;
    
    inline void insert(char *c,int p)
    {
        int len=strlen(c+1),k=0;
        for(register int i=1;i<=len;i++)
        {
            int t=c[i]-'A';
            if(!tr[k][t])tr[k][t]=++cnt;
            k=tr[k][t];
        }
        danger[k]=1;pos[p]=k;
    }
    inline void build()
    {
        for(register int i=0;i<S;i++)if(tr[0][i])fail[tr[0][i]]=0,Q.push(tr[0][i]);
        while(!Q.empty())
        {
            int k=Q.front();Q.pop();
            for(register int i=0;i<S;i++)
            {
                if(!tr[k][i])tr[k][i]=tr[fail[k]][i];
                else
                {
                    fail[tr[k][i]]=tr[fail[k]][i];
                    Q.push(tr[k][i]);
                }
            }
        }
    }
    inline matrix operator * (matrix a,matrix b)
    {
        matrix res;
        for(register int i=0;i<N;i++)
            for(register int j=0;j<N;j++)
                for(register int k=0;k<N;k++)res.m[i][j]+=a.m[i][k]*b.m[k][j];
        return res;
    }
    inline matrix pow(matrix a,int b)
    {
        matrix res;
        for(register int i=0;i<N;i++)res.m[i][i]=1;
        for(;b;b>>=1,a=a*a)if(b&1)res=res*a;
        return res;
    }
    int main()
    {
        //freopen("input.in","r",stdin);
        scanf("%d%d%d",&n,&l,&m);
        for(register int i=0;i<m;i++)
        {
            scanf("%lf%lf",&p,&q);
            pro[i]=p/q;
        }
        for(register int i=1;i<=n;i++)
        {
            scanf("%s",s+1);
            insert(s,i);
        }
        build();
        matrix res;
        for(register int i=0;i<=cnt;i++)
        {
            if(danger[i])res.m[i][i]=1;
            else
            {
                for(register int t=0;t<m;t++)res.m[i][tr[i][t]]+=pro[t];
            }
        }
        
        for(register int i=1;i<=100;i++)res=res*res;
        for(register int i=1;i<=n;i++)printf("%.2lf
    ",res.m[0][pos[i]]);
        return 0;
    }
    View Code
  • 相关阅读:
    [转]《三国演义》人名英文翻译妙评 你也来评评!
    Effective C++:改善程序技术与设计思维的55个有效做法(第三版)(中文版)(预订)Effective C++ 3RD
    A Closer Look At Parallax Occlusion Mapping
    [转]收录全部作品,《寂静岭套装》发售开始
    [转]程序员版《桃花庵》
    Cg 1.5 Beta 2
    FilteredTextBox控件
    CollapsiblePanel控件
    DynamicPopulate控件
    HoverMenu控件的使用
  • 原文地址:https://www.cnblogs.com/yoshinow2001/p/8138282.html
Copyright © 2011-2022 走看看