uva 11468 AC自动机+概率DP

#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdio>
#include<map>
#include<string>
using namespace std;

const int SIGMA_SIZE = 64;
const int MAXNODE = 500; // 结点总数
const int MAXS = 20 + 10; // 模板个数

int idx[256], n;
double prob[SIGMA_SIZE];

struct AhoCorasickAutomata 
{
    int ch[MAXNODE][SIGMA_SIZE];
    int f[MAXNODE];    // fail函数
    int match[MAXNODE];  // 是否包含某一个字符串
    int sz;            // 结点总数

    void init() 
    {
        sz = 1;
        memset(ch[0], 0, sizeof(ch[0]));
    }
    
    // 插入字符串
    void insert(char *s) 
    {
        int u = 0, n = strlen(s);
        for(int i = 0; i < n; i++) 
        {
            int c = idx[s[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;
    }
    
    // 计算fail函数
    void getFail() 
    {
        queue<int> q;
        f[0] = 0;
        // 初始化队列
        for(int c = 0; c < SIGMA_SIZE; c++) 
        {
            int u = ch[0][c];
            if(u) { f[u] = 0; q.push(u); }
        }
        // 按BFS顺序计算fail
        while(!q.empty()) 
        {
            int r = q.front(); q.pop();
            for(int c = 0; c < SIGMA_SIZE; 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[f[u]];
            }
        }
    }
};

AhoCorasickAutomata ac;

double d[MAXNODE][105];
int vis[MAXNODE][105];

double getProb(int u, int L) 
{
    if(!L) return 1.0;
    if(vis[u][L]) return d[u][L];
    vis[u][L] = 1;
    double &ans = d[u][L];
    ans = 0.0;
    for(int i = 0; i < n; i++)
        if(!ac.match[ac.ch[u][i]]) ans += prob[i] * getProb(ac.ch[u][i], L-1);
    return ans;
}

char s[30][30];

int main() 
{
    int T,i,k,L,kase;
    scanf("%d", &T);
    for(kase = 1; kase <= T; kase++) 
    {
        scanf("%d", &k);
        for(i = 0; i < k; i++) scanf("%s", s[i]);
        scanf("%d", &n);
        for(i = 0; i < n; i++) 
        {
            char ch[9];
            scanf("%s%lf", ch, &prob[i]);
            idx[ch[0]] = i;
        }
        ac.init();
        for(i = 0; i < k; i++) ac.insert(s[i]);
        ac.getFail();
        scanf("%d", &L);
        memset(vis, 0, sizeof(vis));
        printf("Case #%d: %.6lf
", kase, getProb(0, L));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xiong-/p/3628300.html