[AC自动机+概率dp] hdu 3689 Infinite monkey theorem

来源:互联网 发布:2016开淘宝店卖什么 编辑:程序博客网 时间:2024/05/29 16:11

题意:

给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%%\n",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%%\n",ans.mat[0][triecont-1]*100);    }    return 0;}



0 0
原创粉丝点击