AC自动机+全概率+记忆化DP UVA 11468 Substring

 

题目传送门

题意:训练指南P217

分析:没有模板串也就是在自动机上走L步,不走到val[u] == v的节点的概率

PS:边读边insert WA了,有毒啊!

#include <bits/stdc++.h>
using namespace std;

const int K = 20 + 5;
const int L = 100 + 5;
const int NODE = K * K;
const int SIZE = 66;
int idx[256], n;
struct AC   {
    int ch[NODE][SIZE], fail[NODE], match[NODE], sz;
    void clear(void)    {
        memset (ch[0], 0, sizeof (ch[0]));
        sz = 1;
    }
    void insert(char *P)    {
        int u = 0, lenp = strlen (P);
        for (int c, i=0; i<lenp; ++i)    {
            c = idx[P[i]];
            if (!ch[u][c])  {
                memset (ch[sz], 0, sizeof (ch[sz]));
                match[sz] = 0;
                ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
        match[u] = 1;
    }
    void build(void)    {
        queue<int> que; fail[0] = 0;
        int u;
        for (int c=0; c<SIZE; ++c)  {
            u = ch[0][c];
            if (u)  {
                fail[u] = 0;    que.push (u);
            }
        }
        while (!que.empty ())   {
            int r = que.front ();   que.pop ();
            for (int c=0; c<SIZE; ++c)  {
                int u = ch[r][c];
                if (!u) {
                    ch[r][c] = ch[fail[r]][c]; continue;
                }
                que.push (u);
                int v = fail[r];
                while (v && !ch[v][c])    v = fail[v];
                fail[u] = ch[v][c];
                match[u] |= match[fail[u]];
            }
        }
    }
}ac;

double prob[SIZE];
bool vis[NODE][L];
double dp[NODE][L];
double DFS(int u, int len)  {
    if (!len)   return 1.0;
    if (vis[u][len])    return dp[u][len];
    vis[u][len] = true;
    double &ret = dp[u][len];
    ret = 0;
    for (int i=0; i<n; ++i) {
        if (!ac.match[ac.ch[u][i]]) ret += prob[i] * DFS (ac.ch[u][i], len - 1);
    }
    return ret;
}
char pattern[30][30];
//char pattern[30];

int main(void)  {
    int T, cas = 0;  scanf ("%d", &T);
    while (T--) {
        //char pattern[30];
        ac.clear ();
        int k;  scanf ("%d", &k);
        for (int i=1; i<=k; ++i)    {
            scanf ("%s", &pattern[i]);
            //scanf ("%s", &pattern);
            //ac.insert (pattern);
        }
        //ac.build ();
        scanf ("%d", &n);
        char str[3];
        for (int i=0; i<n; ++i)    {
            scanf ("%s%lf", &str, &prob[i]);
            idx[str[0]] = i;
        }
        for (int i=1; i<=k; ++i)    ac.insert (pattern[i]);
        ac.build ();
        int len;    scanf ("%d", &len);
        memset (vis, false, sizeof (vis));
        printf ("Case #%d: %.6lf\n", ++cas, DFS (0, len));
    }

    return 0;
}

  

你可能感兴趣的:(AC自动机+全概率+记忆化DP UVA 11468 Substring)