AC自动机 UVa11468

来源:互联网 发布:stm8单片机视频教程 编辑:程序博客网 时间:2024/06/12 21:02

在给定的字符下,任意搭配,不含有任一模板串的概率,抽象的最终问题是:在Trie图上走L步,保证每一步不是单词节点,用记忆化搜索,这是对节点是否为单词节点的标记是match[u] |= match[f[u]],不再需要维护val[u]和last[u]。

还是稍微有些不好理解的。

#include <iostream>#include <fstream>#include <algorithm>#include <cstring>#include <queue>using namespace std;#define SIG 62#define MAX 25*25#define ML 105double prob[SIG];int record[SIG];int n, T, k,  L;char s[40];inline int idx(char c){    if ( c<='9') return c-'0';    if (c>='a') return c-'a'+10;    return c-'A'+36;}struct AC_auto {    int ch[MAX][SIG], f[MAX];    bool match[MAX], vis[MAX][ML];    double d[MAX][ML];    int sz;    void init(){        sz=1;        memset(ch[0],0,sizeof(ch[0]));        memset(match,false,sizeof(match));        memset(vis,false,sizeof(vis));    }    void Insert(char *s){        int u=0, n=strlen(s), c;        for (int i=0;i<n;i++) {            c=idx(s[i]);            if (!ch[u][c]) {                memset(ch[sz],0,sizeof(ch[sz]));                ch[u][c]=sz++;            }            u=ch[u][c];        }        match[u]=true;    }    void getfail(){        queue<int> q;        for (int i=0;i<SIG;i++)            if (ch[0][i]) {                f[ch[0][i]] = 0;                q.push(ch[0][i]);            }        while (!q.empty()) {            int r=q.front();            q.pop();            for (int c=0;c<SIG;c++){                int u=ch[r][c];                if (!u) {                    ch[r][c]=ch[f[r]][c];                    continue;                }                q.push(u);                int v=f[r];                while (v && !ch[v][c]) v=f[v];                f[u]=ch[v][c];                match[u] = match[u] | match[f[u]];            }        }    }    double getProb(int u,int L){        if (!L) return 1.0;        if (vis[u][L]) return d[u][L];        vis[u][L]=true;        double &ans=d[u][L];        ans=0.0;        for (int i=0;i<n;i++)            if (!match[ch[u][record[i]]])                ans+=prob[record[i]]*getProb(ch[u][record[i]],L-1);        return ans;    }}ac;void del(){        ac.init();        for (int i=0;i<SIG;i++) prob[i]=0.0;        scanf("%d",&k);        for (int i=0;i<k;i++){            scanf("%s",s);            ac.Insert(s);        }        ac.getfail();        scanf("%d",&n);        for (int i=0;i<n;i++) {            scanf("%s",s);            record[i]=idx(s[0]);            scanf("%lf",&prob[record[i]]);        }        scanf("%d",&L);}int main(){    freopen("1.in","r",stdin);    scanf("%d",&T);    int t=T;    while (T--) {        del();        printf("Case #%d: %.6f\n",t-T,ac.getProb(0,L));    }    return 0;}


原创粉丝点击