• uva 11468 Substring


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

    给出一些字符和各自对应的选择概率,随机选择L次后得到一个长度为L的随机字符串S。

    给出K个模板串,计算S不包含任何一个模板串的概率

    dp[i][j]表示现在在AC自动机的i号点,还需要走j步的概率

    dp[i][j]=Σdp[k][j-1] ,k不是单词节点

    注意:

    1、模板串可能是模板串的后缀,所以这题要用AC自动机,而不是Trie

    2、在构造失配指针时,如果边不存在,要补上,边(不是失配指针)指向父节点的失配指针的子节点

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    char s[21];
    int len,tot,trie[21*21][63];
    bool mark[21*21],v[21*21][21*21];
    double p[21*21],dp[21*21][21*21];
    char ch[21*21];
    int f[21*21];
    int n;
    queue<int>q;
    int get(char c)
    {
        if(c>='0'&&c<='9') return c-'0';
        if(c>='a'&&c<='z') return c-'a'+10;
        return c-'A'+36;
    }
    void insert()
    {
        len=strlen(s);
        int root=1,id;
        for(int i=0;i<len;i++)
        {
            id=get(s[i]);
            if(!trie[root][id]) 
            {
                trie[root][id]=++tot;
                memset(trie[tot],0,sizeof(trie[tot]));
                mark[tot]=0;
            }
            root=trie[root][id];
        }
        mark[root]=true;
    }
    void getfail()
    {
        memset(f,0,sizeof(f));
        for(int i=0;i<63;i++) trie[0][i]=1;
        q.push(1);
        int now,j;
        while(!q.empty())
        {
            now=q.front(); q.pop(); 
            for(int i=0;i<63;i++)
            {
                if(!trie[now][i]) 
                {
                    trie[now][i]=trie[f[now]][i];
                    continue;
                }
                q.push(trie[now][i]);
                j=f[now];
                f[trie[now][i]]=trie[j][i];
                if(mark[trie[j][i]]) mark[trie[now][i]]=true;
            }
        }
    }
    double dpp(int now,int L)
    {
        if(!L) return 1.0;
        if(!now) now=1;
        if(v[now][L]) return dp[now][L];
        v[now][L]=true;
        double ans=0.0;
        for(int i=1;i<=n;i++) 
        {
            int id=get(ch[i]);
            if(!mark[trie[now][id]]) ans+=p[i]*dpp(trie[now][id],L-1);
        }
        return dp[now][L]=ans;
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        for(int t=1;t<=T;t++)
        {
            scanf("%d",&n);
            memset(trie[1],0,sizeof(trie[1]));
    //        memset(dp,0,sizeof(dp));
            memset(v,0,sizeof(v));
            tot=1;
            while(n--)
            {
                scanf("%s",s);
                insert();
            }
            getfail();
            scanf("%d",&n);
            for(int i=1;i<=n;i++) 
            {
                cin>>ch[i];
                scanf("%lf",&p[i]);
            }
            int L;
            scanf("%d",&L);
            printf("Case #%d: %.6lf
    ",t,dpp(1,L));
        }
    }

    另一种构造失配指针的写法

    2个地方不一样

    1、AC自动机从0开始,上面0作为虚拟节点

    2、0不能直接入队,枚举0节点的孩子,让孩子入队

        因为0的失配指针是0

     f[trie[now][i]]=trie[j][i]=trie[0][i]=本节点
    导致失配指针指向自己

    上面让1入队,1的失配指针是0

       

    void getfail()
    {
        memset(f,0,sizeof(f));
        for(int i=0;i<63;i++) 
          if(trie[0][i]) q.push(trie[0][i]);
        int now,j;
        while(!q.empty())
        {
            now=q.front(); q.pop(); 
            for(int i=0;i<63;i++)
            {
                if(!trie[now][i]) 
                {
                    trie[now][i]=trie[f[now]][i];
                    continue;
                }
                q.push(trie[now][i]);
                j=f[now];
                //while(!trie[j][i]) j=f[j];
                f[trie[now][i]]=trie[j][i];
                if(mark[trie[j][i]]) mark[trie[now][i]]=true;
            }
        }
    }
  • 相关阅读:
    Chrome Extension 扩展程序 小白入门
    gulp 打包报错:ReferenceError: internalBinding is not defined
    error in static/js/xxx.js from UglifyJs Unpected token: punc() [static/js/xxx.js]
    ES6-
    浏览器的渲染原理(转载)
    nodeType、nodeName和nodeValue
    浏览器 HTTP 协议缓存机制详解
    JS函数的上下文环境
    ready和onload的区别
    自定义事件
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6961632.html
Copyright © 2020-2023  润新知