zoukankan      html  css  js  c++  java
  • UVA 11468 AC 自动机

    首先我们应该是枚举 L个位置上的每个字符来得到最终概率

    然后AC自动机的作用就是为了判断你枚举的地方是否对应了单词节点,如果对应了,就肯定要不得

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const int max_node = 500;
    const int N =256;
    const int node_num=64;
    int idx[N],k,n;
    char str[30][30];
    double prob[100]; //这个地方一开始开小了,题目也没说n为多少。坑啊。。一直RE没找到原因
    int vis[max_node][110]; 
    double d[max_node][110];
    struct ACtrie
    {
        int ch[max_node][64];
        int sz;
        int val[max_node];
        int fail[max_node];
        //int last[max_node];
        void init(){
            memset(ch,0,sizeof ch);
            memset(val,0,sizeof val);
            memset(fail,0,sizeof fail);
            //memset(last,0,sizeof last);
            sz=1;
        }
        void insert(char* s,int v){
            int u=0;
            for (int i=0;s[i];i++){
                int c=idx[s[i]];
                if (!ch[u][c]){
                    memset(ch[sz],0,sizeof ch[sz]);
                    val[sz]=0;
                    ch[u][c]=sz++;
                }
                u=ch[u][c];
            }
            val[u]=1;
        }
        void getfail(){
            queue<int> q;
            fail[0]=0;
            for (int i=0;i<node_num;i++)
                if (ch[0][i]){
                    fail[ch[0][i]]=0;
                    q.push(ch[0][i]);
                }
    
            while (!q.empty()){
                int u=q.front();
                q.pop();
                for (int c=0;c<node_num;c++){
                    int v=ch[u][c];
                    if (!v) {ch[u][c] = ch[fail[u]][c];continue;} //这个个普通AC自动机不一样,因为要一视同仁所有字符,当前字符在该子树如果找不到就可以转到其失败节点去,因为失败节点有的话,同样是满足条件的
                    q.push(v);
                    int p=fail[u];
                    while (p && !ch[p][c]) p=fail[p];
                    fail[v]=ch[p][c];
                    //last[v]=val[fail[p]]?fail[p] : last[fail[p]];
                    val[v]|=val[fail[v]];
                }
            }
        }
    } T;
    double getprob(int u,int L)
    {
        if (L==0) return 1.0;
        if (vis[u][L]) return d[u][L];
        vis[u][L]=1;
        d[u][L]=0.0;
        for (int i=0;i<n;i++){
            if (!T.val[T.ch[u][i]]) d[u][L]+=prob[i]*getprob(T.ch[u][i],L-1);
        }
        return d[u][L];
    }
    int main()
    {
        int t,L;
        char cc[9];
        scanf("%d",&t);
        int kase=0;
        while (t--){
            T.init();
            scanf("%d",&k);
            for (int i=0;i<k;i++)
                scanf("%s",str[i]);
            scanf("%d",&n);
            for (int i=0;i<n;i++){
              scanf("%s%lf",&cc,&prob[i]);
              idx[cc[0]]=i;
            }
            for (int i=0;i<k;i++){
                T.insert(str[i],1);
            }
            T.getfail();
            memset(vis,0,sizeof vis);
            scanf("%d",&L);
            double ans=getprob(0,L);
            printf("Case #%d: %.6lf
    ",++kase,ans);
        }
        return 0;
    }
  • 相关阅读:
    自定义 Laravel 5.7
    1项目环境配置和用户表设计
    Laravel 6.X + Vue.js 2.X + Element UI 开发知乎流程
    component:(resolve) => require
    Vue2.0 render:h => h(App)
    techiediaries Vuejs教程
    techiediaries网站的Laravel 6系列教程
    合并结果插件
    SQLMAP
    CNC MacroProgram
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3669726.html
Copyright © 2011-2022 走看看