• UVA


      建立AC自动机,把AC自动机当做一张图,在上面跑L个节点就行了。

      参考了刘汝佳的代码,发现可能有一个潜在的Bug--如果模式串中出现了没有指定的字符,AC自动机可能会建立出错。

    提供一组关于这个BUG的数据:

    这组数据我觉得答案应该是1吧,无论如何组合'a'和'b'这两个字符,也无法得到模式串"ac"和"bd"!!

    AC代码

    #include <stdio.h>
    #include <string.h>
    #include <queue>
    #include <map>
    using namespace std;
    
    const int maxnode = 20 * 20 + 5;
    const int segma_size = 26 + 26 + 10;
    const int maxn = 26 + 26 + 10 + 5;
    const int maxs = 20 + 5;
    double prob[maxn];
    int id[256], n, k;
    char s[maxs][maxs];
    
    struct Aho{
        int ch[maxnode][segma_size];
        int f[maxnode];
        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);
            // try to fix bug
            for(int i = 0; i < n; i++) {
                int c = id[s[i]];
                if(c == -1) return;
            }
            
            for(int i = 0; i < n; i++) {
                int c = id[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;
        }
        
        void getFail() {
            f[0] = 0;
            queue<int> q;
            for(int i = 0; i < n; i++) {
                int u = ch[0][i];
                if(u) { f[u] = 0; q.push(u); }
            }
            
            while(!q.empty()) {
                int r = q.front(); q.pop();
                for(int c = 0; c < n; 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]]; 
                }
            }
        }
        
    }ac;
    
    double d[maxnode][105];
    bool vis[maxnode][105];
    
    double solve(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 c = 0; c < n; c++) {
            if(!ac.match[ac.ch[u][c]]) ans += prob[c] * solve(ac.ch[u][c], L-1);
        }
        return ans;
    }
    
    int main() {
        int T, kase = 1;
        scanf("%d", &T);
        while(T--) {
            scanf("%d", &k);
            for(int i = 0; i < k; i++) {
                scanf("%s", s[i]);
            }
            scanf("%d", &n);
            char ch[5];
            memset(id, -1, sizeof(id));
            for(int i = 0; i < n; i++) {
                scanf("%s%lf", ch, &prob[i]);
                id[ch[0]] = i;
            }
            ac.init();
            for(int i = 0; i < k; i++) ac.insert(s[i]);
            ac.getFail();
            int L;
            scanf("%d", &L);
            memset(vis, 0, sizeof(vis));
            printf("Case #%d: %.6f
    ", kase++, solve(0, L));
        }
        return 0;
    }
  • 相关阅读:
    JS轮播图
    jquery 60秒倒计时
    jQuery 显示加载更多
    jQuery 显示加载更多
    this指针在不同情况下的指代
    web-app1--移动端等比例代码
    无障碍阅读
    javascript+dom 做javascript图片库
    初探html5---Video + DOM(视频播放)
    14个有效提高网站Banner点击率的设计技巧分享
  • 原文地址:https://www.cnblogs.com/flyawayl/p/8902106.html
Copyright © 2020-2023  润新知