[AC自动机+dp] whu oj 1572 I - Cyy and Fzz

来源:互联网 发布:js 人民币大写在线 编辑:程序博客网 时间:2024/06/04 19:04

题意:

给你n个串,求长度为l的串包含n个串个数的期望。

思路:

自动机dp[i][j][k] 长度为i在节点j状态为k的概率。

然后遍历一遍求期望。

代码:

#include"cstdlib"#include"cstdio"#include"cstring"#include"cmath"#include"queue"#include"algorithm"#include"iostream"#include"map"#include"stack"#define N 123#define eps 1e-8using namespace std;double dp[20][N][277];int n,len;struct Trie{    int next[N][27],fail[N],mark[N];    int root,L;    int newnode()    {        memset(next[L],-1,sizeof(next[L]));        mark[L]=0;        fail[L++]=-1;        return L-1;    }    void go()    {        L=0;        root=newnode();    }    void init(char *v,int id)    {        int p=root;        for(int i=0; v[i]; i++)        {            int tep=v[i]-'a';            if(next[p][tep]==-1) next[p][tep]=newnode();            p=next[p][tep];        }        mark[p]|=(1<<id);    }    void build()    {        queue<int>q;        q.push(root);        while(!q.empty())        {            int p=q.front();            q.pop();            for(int i=0; i<26; i++)            {                if(next[p][i]==-1)                {                    if(p==root) next[p][i]=root;                    else next[p][i]=next[fail[p]][i];                }                else                {                    if(p==root) fail[next[p][i]]=root;                    else fail[next[p][i]]=next[fail[p]][i];                    q.push(next[p][i]);                    if(p!=root) mark[next[p][i]]|=mark[next[fail[p]][i]];                }            }        }    }    void solve()    {        memset(dp,0,sizeof(dp));        dp[0][0][0]=1.0;        for(int i=1; i<=len; i++)        {            for(int j=0; j<L; j++)            {                for(int k=0; k<(1<<n); k++)                {                    for(int o=0; o<26; o++)                    {                        int tep=next[j][o];                        dp[i][tep][mark[tep]|k]+=1.0/26*dp[i-1][j][k];                    }                }            }        }        double ans=0;        for(int i=0; i<L; i++)        {            for(int j=1; j<(1<<n); j++)            {                int cnt=0;                for(int k=0; k<n; k++) if(j&(1<<k)) cnt++;                ans+=cnt*dp[len][i][j];            }        }        printf("%.6f\n",ans);    }} ac;int main(){    int t;    cin>>t;    while(t--)    {        scanf("%d%d",&n,&len);        ac.go();        for(int i=0; i<n; i++)        {            char x[123];            scanf("%s",x);            ac.init(x,i);        }        ac.build();        ac.solve();    }    return 0;}


0 0
原创粉丝点击