UVA 11468 Substring(ac自动机+DP)

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2463

题意:给出一个字母表以及每个字母出现的概率。再给出一些模板串S。从字母表中每次随机拿出一个字母,一共拿L次组成一个产度为L的串,问这个串不包含S中任何一个串的概率为多少?

思路:首先将模板串S建立自动机。 然后就是DP。f[i][j]表示长度为i在j节点上的概率。注意,给出的字母表有多少个字母自动机里就要使用多少个字母。

 





struct node
{
    int c[62];
    int fail,flag;
    
    void init()
    {
        clr(c,0); fail=-1; flag=0;
    }
};




node a[N];
int cnt,mp[130];
int Sum;




void insert(char *s)
{
    int i,x,p=0;
    for(i=0;s[i];i++)
    {
        x=mp[s[i]];
        if(!a[p].c[x]) 
        {
            a[p].c[x]=++cnt;
            a[cnt].init();
        }
        p=a[p].c[x];
    }
    a[p].flag=1;
}




void build()
{
    queue<int> Q;
    int i,u,p,q;
    Q.push(0);
    while(!Q.empty())
    {
        u=Q.front();
        Q.pop();
        
        FOR0(i,Sum)
        {
            if(a[u].c[i]!=0)
            {
                p=a[u].c[i];
                q=a[u].fail;
                if(q!=-1) a[p].fail=a[q].c[i];
                else a[p].fail=0;
                a[p].flag|=a[a[p].fail].flag;
                Q.push(p);
            }
            else
            {
                q=a[u].fail;
                if(q!=-1) a[u].c[i]=a[q].c[i];
                else a[u].c[i]=0;
            }
        }
    }
}




int n,m,L;
char s[N][25],S[N];
double p[N],f[105][N];
int b[N];


int main()
{
    int num=0;
    rush()
    {
        a[0].init(); cnt=0;
        RD(n);
        int i;
        FOR0(i,n) RD(s[i]);
        RD(m);
        Sum=0;
        FOR1(i,m)
        {
            RD(S); mp[S[0]]=Sum++; 
            RD(p[mp[S[0]]]);
        }
        FOR0(i,n) insert(s[i]);
        build();
        RD(L);
        printf("Case #%d: ",++num);
        clr(f,0);
        f[0][0]=1;
        int j,k,t;
        
        for(i=0;i<L;i++) for(j=0;j<=cnt;j++) if(!a[j].flag)
        {
            for(k=0;k<Sum;k++)
            {
                t=a[j].c[k];
                if(!a[t].flag) f[i+1][t]+=f[i][j]*p[k];
            }
        }
        double ans=0;
        for(i=0;i<=cnt;i++)  ans+=f[L][i];
        PR(ans);
    }
}

你可能感兴趣的:(substring)