• UVA11468 Substring


    思路

    AC自动机+概率dp

    设f[i][j]表示当前在第i位在AC自动机的第j个节点,满足条件的概率

    AC自动机上的一个节点能被转移到当且仅当这个节点不是中止节点且无法通过fail指针跳到任何一个中止节点

    答案就是(sum_{xin node} dp[L][x])

    注意本题字符集为0~9,A~Z,a~z

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    using namespace std;
    int Trie[410][64],fail[410],Nodecnt,root,ban[410],a[410],K,N,L;
    double f[110][410],p[410];
    char s[410];
    int tonum(char c){
        if(c>='a'&&c<='z')
            return c-'a';//0~25
        else if(c>='A'&&c<='Z')
            return c-'A'+26;//26~51
        else if(c>='0'&&c<='9')
            return c-'0'+52;
    }
    void insert(char *s,int len){
        int o=root;
        for(int i=0;i<len;i++){
            if(!Trie[o][tonum(s[i])])
                Trie[o][tonum(s[i])]=++Nodecnt;
            o=Trie[o][tonum(s[i])];
        }
        ban[o]=true;
    }
    queue<int> q;
    void get_AC(void){
        for(int i=0;i<64;i++){
            if(Trie[root][i]){
                fail[Trie[root][i]]=root;
                if(ban[fail[Trie[root][i]]])
                    ban[Trie[root][i]]=true;
                q.push(Trie[root][i]);            
            }
        }
        while(!q.empty()){
            int x=q.front();
            q.pop();
            for(int i=0;i<64;i++){
                if(Trie[x][i]){
                    fail[Trie[x][i]]=Trie[fail[x]][i]; 
                    if(ban[fail[Trie[x][i]]])
                        ban[Trie[x][i]]=true;
                    q.push(Trie[x][i]);
                }
                else
                    Trie[x][i]=Trie[fail[x]][i];
            }
        }
    }
    double dp(void){
        int o=root;
        f[0][root]=1.0;
        for(int i=0;i<L;i++){
            for(int j=0;j<=Nodecnt;j++)
                if(!ban[j])
                    for(int k=1;k<=N;k++)
                        if(!ban[Trie[j][tonum(a[k])]])
                            f[i+1][Trie[j][tonum(a[k])]]+=f[i][j]*p[k];
        }
        double ans=0;
        for(int i=0;i<=Nodecnt;i++)
            ans+=f[L][i];
        return ans;
    }
    void init(void){
        Nodecnt=0;
        root=0;
        memset(Trie,0,sizeof(Trie));
        memset(fail,0,sizeof(fail));
        memset(f,0,sizeof(f));
        memset(ban,0,sizeof(ban));
    }
    int main(){
        // freopen("test.in","r",stdin);
        // freopen("test.out","w",stdout);
        int T,cnt=0;
        scanf("%d",&T);
        while(T--){
            cnt++;
            init();
            scanf("%d",&K);
            for(int i=1;i<=K;i++){
                scanf("%s",s);
                insert(s,strlen(s));
            }
            scanf("%d",&N);
            for(int i=1;i<=N;i++){
                char c=getchar();
                while((c<'a'||c>'z')&&(c<'A'||c>'Z')&&(c<'0'||c>'9'))
                    c=getchar();
                // printf("c=%c
    ",c);
                a[i]=c;
                scanf("%lf",&p[i]);
            }
            scanf("%d",&L);
            get_AC();
            printf("Case #%d: %.6lf
    ",cnt,dp());
        }
        return 0;
    }
    
  • 相关阅读:
    性能百万/s:腾讯轻量级全局流控方案详解
    Swagger2
    shiro 入门
    01、单例模式
    02、工厂方法
    04、模板模式
    13、Adapter 适配器
    14、迭代器
    Java 面向切面 AOP
    spring boot 中使用 Redis 与 Log
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10693999.html
Copyright © 2020-2023  润新知