• [AC自己主动机+可能性dp] hdu 3689 Infinite monkey theorem


    意甲冠军:

    给n快报,和m频率。

    然后进入n字母出现的概率

    然后给目标字符串str

    然后问m概率倍的目标字符串是敲数量。

    思维:

    AC自己主动机+可能性dp简单的问题。

    首先建立trie图,然后就是状态转移了

    dp版本号:

     dp三重循环变量次数,节点数,和字母数

    代码:

    #include"cstdlib"
    #include"cstdio"
    #include"cstring"
    #include"cmath"
    #include"queue"
    #include"algorithm"
    #include"iostream"
    #include"map"
    #include"string"
    using namespace std;
    int triecont;
    double dp[1234][22];
    struct trie
    {
        int mark,id;
        trie *next[27],*fail;
        trie()
        {
            mark=id=0;
            memset(next,0,sizeof(next));
            fail=NULL;
        }
    };
    trie *root,*node[22];
    void init(char *v)
    {
        trie *p=root;
        for(int i=0;v[i];i++)
        {
            int tep=v[i]-'a';
            if(p->next[tep]==NULL)
            {
                p->next[tep]=new trie();
                node[triecont]=p->next[tep];
                p->next[tep]->id=triecont++;
            }
            p=p->next[tep];
        }
        p->mark++;
    }
    void getac()
    {
        queue<trie*>q;
        q.push(root);
        while(!q.empty())
        {
            trie *p=q.front();
            q.pop();
            for(int i=0;i<26;i++)
            {
                if(p->next[i]==NULL)
                {
                    if(p==root) p->next[i]=root;
                    else p->next[i]=p->fail->next[i];
                }
                else
                {
                    if(p==root) p->next[i]->fail=root;
                    else p->next[i]->fail=p->fail->next[i];
                    q.push(p->next[i]);
                }
            }
        }
    }
    int main()
    {
        int n,m;
        while(scanf("%d%d",&n,&m),(n+m))
        {
            double gl[27];
            memset(gl,0,sizeof(gl));
            memset(node,0,sizeof(node));
            while(n--)
            {
                char x[2];
                double y;
                scanf("%s%lf",x,&y);
                gl[x[0]-'a']=y;
            }
            char fuck[27];
            scanf("%s",fuck);
            triecont=0;
            root=new trie();
            node[triecont]=root;
            root->id=triecont++;
            init(fuck);
            getac();
            memset(dp,0,sizeof(dp));
            dp[0][0]=1;
            for(int i=1;i<=m;i++)
            {
                for(int j=0;j<triecont-1;j++)
                {
                    for(int k=0;k<26;k++)
                    {
                        trie *p=node[j]->next[k];
                        dp[i][p->id]+=dp[i-1][j]*gl[k];
                    }
                }
            }
            double ans=0;
            for(int i=0;i<=m;i++) ans+=dp[i][triecont-1];
    
            printf("%.2f%%
    ",ans*100);
        }
        return 0;
    }
    

    建立可达矩阵版本号:

    注意到达目标状态 那么他之后的状态的概率就都是1了

    然后用高速幂加速~

    #include"cstdlib"
    #include"cstdio"
    #include"cstring"
    #include"cmath"
    #include"queue"
    #include"algorithm"
    #include"iostream"
    using namespace std;
    int triecont;
    struct trie
    {
        int mark,id;
        trie *next[27];
        trie *fail;
        trie()
        {
            mark=id=0;
            memset(next,0,sizeof(next));
            fail=NULL;
        }
    };
    struct matrix
    {
        double mat[20][20];
    };
    trie *root;
    void init(char *v)
    {
        trie *p=root;
        for(int i=0; v[i]; i++)
        {
            int tep=v[i]-'a';
            if(p->next[tep]==NULL)
            {
                p->next[tep]=new trie();
                p->next[tep]->id=triecont++;
            }
            p=p->next[tep];
        }
        p->mark=1;
    }
    void getac()
    {
        queue<trie*>q;
        q.push(root);
        while(!q.empty())
        {
            trie *p;
            p=q.front();
            q.pop();
            for(int i=0; i<26; i++)
            {
                if(p->next[i]==NULL)
                {
                    if(p==root) p->next[i]=root;
                    else p->next[i]=p->fail->next[i];
                }
                else
                {
                    if(p==root) p->next[i]->fail=root;
                    else  p->next[i]->fail=p->fail->next[i];
                    q.push(p->next[i]);
                }
            }
        }
    }
    matrix matmul(matrix a,matrix b,int n)
    {
        int i,j,k;
        matrix c;
        memset(c.mat,0,sizeof(c.mat));
        for(i=0; i<n; i++)
        {
            for(j=0; j<n; j++)
            {
                for(k=0; k<n; k++)
                {
                    c.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
                }
            }
        }
        return c;
    }
    matrix matpow(matrix a,int k,int n)
    {
        matrix b;
        int i;
        memset(b.mat,0,sizeof(b.mat));
        for(i=0; i<n; i++) b.mat[i][i]=1;
        while(k)
        {
            if(k&1) b=matmul(a,b,n);
            a=matmul(a,a,n);
            k>>=1;
        }
        return b;
    }
    int main()
    {
        int n,m;
        while(scanf("%d%d",&n,&m),(n+m))
        {
            double gl[27];
            memset(gl,0,sizeof(gl));
            while(n--)
            {
                char x[2];
                double y;
                scanf("%s%lf",x,&y);
                gl[x[0]-'a']+=y;
            }
            triecont=0;
            root=new trie();
            root->id=triecont++;
            char x[12];
            scanf("%s",x);
            init(x);
            getac();
            queue<trie*>q;
            q.push(root);
            int used[12];
            memset(used,0,sizeof(used));
            matrix a,ans;
            memset(a.mat,0,sizeof(a.mat));
            while(!q.empty())
            {
                trie *p=q.front();
                q.pop();
                if(used[p->id]) continue;
                used[p->id]=1;
                if(p->mark==1)        //目标状态 兴许状态都是本身
                {
                    a.mat[p->id][p->id]=1;
                    continue;
                }
                for(int i=0;i<26;i++)
                {
                    if(used[p->next[i]->id]==0) q.push(p->next[i]);
                    a.mat[p->id][p->next[i]->id]+=gl[i];
                }
            }
            /*for(int i=0;i<triecont;i++)
            {
                for(int j=0;j<triecont;j++) printf("%.2f ",a.mat[i][j]);
                puts("");
            }*/
            ans=matpow(a,m,triecont);
            printf("%.2f%%
    ",ans.mat[0][triecont-1]*100);
        }
        return 0;
    }
    



    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    TRUNCATE TABLE 删除表中的所有行,而不记录单个行删除操作
    血腥!实况转播SQL注入全过程,让你知道危害有多大。
    DB2隔离级别设置
    使用解释工具分析SQL语句
    DB2的七种武器
    db2精华文档和论坛链接
    “饮水机”:形象比喻 深入浅出理解RAID
    DB2 数据库恢复测试
    IBM DB2 日常维护汇总
    镜像分割与高可用性灾难恢复
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4624573.html
Copyright © 2020-2023  润新知