zoukankan      html  css  js  c++  java
  • uva-11468

    AC自动机+dp(记忆化搜素)

    https://vjudge.net/problem/UVA-11468

    思路:构造出AC自动机后,把所有单词节点标记为禁止,就转化为从0节点走L步不进入任何禁止节点的概率。令dp[i][j]等于在i节点还要走j步不碰到禁忌节点的概率。

    #include<iostream>
    #include<iomanip>
    #include<cstring>
    #include<sstream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<stdlib.h>
    #include<string>
    #include<queue>
    #include<vector>
    #include<map>
    #include<stack>
    //#include<bits/stdc++.h>
    #define _for(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    typedef long long ll;
    const int mod =1e6+7;
    double esp=1e-6;
    int INF =0x3f3f3f3f;
    const int inf = 1<<28;
    const int MAXN=3e5+5;
    int ch[500][70];
    int tot,k,n,m,fail[500];
    bool en[500],vis[500][110];
    double dp[500][110],p[100];
    map<char,int> mp;
    char s[30][30];
    void insertword(char *s)
    {
        int u=0;
        int len=strlen(s);
        for(int i=0;i<len;i++)
        {
            int v=mp[s[i]];
            if(!ch[u][v])
            {
                ch[u][v]=++tot;
            }
            u=ch[u][v];
        }
        en[u]=1;
    }
    void getfail()
    {
        queue<int> q;
        for(int i=0;i<m;i++)
        {
            if(ch[0][i])
            {
                q.push(ch[0][i]);
            }
        }
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int i=0;i<m;i++)
            {
                if(ch[u][i])
                {
                    fail[ch[u][i]]=ch[fail[u]][i];
                    en[ch[u][i]]|=en[fail[ch[u][i]]];//注意更新不能走的位置
                    //因为如果选这个点,而这个点的失配指针指向的位置en是1
                    //说明在当前单词位置向前若干个字母会形成和另外单词一样的单词(包含关系)
                    q.push(ch[u][i]);
                    //printf("%d %d %d
    ",ch[u][i],en[ch[u][i]],en[fail[ch[u][i]]]);
                }
                else
                    {ch[u][i]=ch[fail[u]][i];}
            }
        }
    }
    double solve(int u,int l)
    {
        if(!l)return 1.0;
        if(vis[u][l])return dp[u][l];
        vis[u][l]=1;
        double &ans=dp[u][l];
        ans=0.0;
        for(int i=0;i<m;i++)
        {
            if(!en[ch[u][i]])ans+=p[i]*solve(ch[u][i],l-1);
        }
        return ans;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        for(int i=1;i<=t;i++)
        {
            tot=0;
            memset(en,0,sizeof(en));
            memset(vis,0,sizeof(vis));
            memset(dp,0,sizeof(dp));
            memset(fail,0,sizeof(fail));
            memset(ch,0,sizeof(ch));
            mp.clear();
            scanf("%d",&k);
            for(int j=1;j<=k;j++)
            {
                scanf("%s",&s[j]);
            }
            scanf("%d",&m);
            for(int j=0;j<m;j++)
            {
                char ss[2];
                scanf("%s",&ss);
                scanf("%lf",&p[j]);
                mp[ss[0]]=j;
            }
            for(int j=1;j<=k;j++)
                insertword(s[j]);
            getfail();
            scanf("%d",&n);
            printf("Case #%d: %0.6lf
    ",i,solve(0,n));
        }
        return 0;
    }
  • 相关阅读:
    [转]zookeeper-端口说明
    ACM-ICPC(9/26)
    ACM-ICPC(9/25)
    Linux的文件权限与目录配置
    Uva 11468 AC自动机或运算
    Uva 11922 Splay
    HDU 6214 最小割边
    Uva 10559 消除方块
    HDU 6194 后缀数组
    Uva 11491 暴力贪心
  • 原文地址:https://www.cnblogs.com/kayiko/p/12305912.html
Copyright © 2011-2022 走看看