zoukankan      html  css  js  c++  java
  • UVA

    随机生成一个字符可以看成在AC自动机里面向前走一个节点,那么ans就是0向前走L步并且不经过单词节点,

    由概率知识可得,f[p][L]=∑f[nxt[p][i]][L-1]*g[i] 其中p表示位于p节点,还要走L步,边界是f[p][0]=1.0,可以用记忆化搜索

    非常巧妙的做法

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #define MAXN 25*25+10
    using namespace std;
    struct AC{
        int nxt[MAXN][65];
        int f[MAXN];
        int match[MAXN];
        int m;
        char ch[65];
        double g[65];
        int cnt;
        int vis[MAXN][MAXN];
        double ans[MAXN][MAXN];
        void init(){
            memset(vis,0,sizeof(vis));
            memset(nxt,0,sizeof(nxt));
            memset(f,0,sizeof(f));
            memset(match,0,sizeof(match));
            cnt=0;
        }
        int dex(char c){
            if('a'<=c&&c<='z')return c-97;
            if('A'<=c&&c<='Z')return c-65+26;
            return c-48+52;
        }
        void insert(char s[]){
            int p=0;
            int len=strlen(s);
            for(int i=0;i<len;i++){
                int t=dex(s[i]);
                if(!nxt[p][t]){
                    nxt[p][t]=(++cnt);
                }
                p=nxt[p][t];
            }
            match[p]=1;
        }
        double work(int p,int L){
            if(!L)return 1.0;
            if(vis[p][L])return ans[p][L];
            vis[p][L]=1;
            double &ret=ans[p][L];
            ret=0.0;
            for(int i=1;i<=m;i++){
                int t=dex(ch[i]);
                if(!match[nxt[p][t]]){
                    ret+=g[i]*work(nxt[p][t],L-1);
                }    
            }
            return ret;
        }
        void getFail(){
            queue<int> q;
            for(int i=0;i<65;i++){
                if(nxt[0][i]){
                    q.push(nxt[0][i]);
                }
            }
            while(!q.empty()){
                int x=q.front();q.pop();
                for(int i=0;i<65;i++){
                    int y=nxt[x][i];
                    if(!y){nxt[x][i]=nxt[f[x]][i];continue;}
                    f[y]=nxt[f[x]][i];
                    match[y]|=match[f[y]];
                    q.push(y);
                }
            }
        }
    }A;
    int n,m,L;
    char s[105];
    void solve(){
        A.init();
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",s);
            A.insert(s);
        }
        A.getFail();
        scanf("%d",&m);
        A.m=m;
        for(int i=1;i<=m;i++){
            double t;
            scanf("%s%lf",s,&t);
            A.ch[i]=s[0];
            A.g[i]=t;
        }    
        scanf("%d",&L);
        printf("%.6f
    ",A.work(0,L));
    }
    int main()
    {
    //    freopen("data.in","r",stdin);
        int T;
        scanf("%d",&T);
        for(int i=1;i<=T;i++){ 
            printf("Case #%d: ",i);
            solve();
        }
        return 0;
    }    
  • 相关阅读:
    四则运算
    Git工具学习整理
    java拦截器中使用的动态代理
    Java动态代理
    Git常用命令
    Maven学习
    ruby调用jenkins API使用
    c#认证考试第四章(国庆作业及其总结)
    C#认证考试第三章
    c#认证考试练习题目
  • 原文地址:https://www.cnblogs.com/w-h-h/p/7923601.html
Copyright © 2011-2022 走看看