HDU 3689 Infinite monkey theorem (uva11468)ac自动机+dp

ac自动机+dp, 和uva11468 Substring 几乎一样,但访问数组d[1010][30]时,下标写反了,但是结果不对,但是没有报错,表示不解
const int MAX = 30;
const int SIGMEA_SIZE = 26;

int m, L;
//double dp[1010][30];
double d[1010][30];
bool vis[1010][30];

char ca[30];

char a[30];
double b[30];

struct AC{
    int ch[MAX][SIGMEA_SIZE];
    int val[MAX];
    int f[MAX];
    int sz;

    ///trie;
    void init()
    {
        sz=1;
        memset(ch,0,sizeof(ch));
        memset(val,0,sizeof(val));///
    }///init;
    int idx(char c) { return c-'a'; }
    void insert(char *s,int v)
    {
        int u=0,n=strlen(s);
        for(int i=0;i<n;i++)
        {
            int c=idx(s[i]);
            if(!ch[u][c])
                ch[u][c] = sz++;
            u = ch[u][c];
        }
        val[u] = v;///
    }
    ///bfs,fail[];
    void getFail()
    {
        queue<int> q;
        f[0] = 0;///
        //初始化队列
        for(int c = 0; c < SIGMEA_SIZE; c++)
        {
            int u = ch[0][c];
            if(u) { f[u] = 0; q.push(u); }///
        }

        while(!q.empty())
        {
            int r = q.front(); q.pop();
            for(int c = 0; c < SIGMEA_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];
                val[u] |= val[f[u]];
            }
        }
    }

    ///dp[l, u]表示敲到l的长度,在状态u位置时的概率
//    double solve()
//    {
//        CLR(dp, 0);
//        dp[0][0] = 1.0;
//        REP(i, L)
//        {
//            REP(j, sz - 1)///!!!
//            {
//                if (i >= j)
//                {
//                    REP(r, m)
//                    {
//                        int c = idx(a[r]);
//                        int v = ch[j][c];
//                        dp[i + 1][v] += b[c] * dp[i][j];
//                    }
//                }
//            }
//        }
//        double ans = 0.0;
//        FE(i, 1, L)
//            ans += dp[i][sz - 1];
//        printf("%.2lf%%\n", ans * 100);
//    }

    ///dp[l, u]表示从状态u出发,敲l的长度,包含串的概率
    ///含的概率,最后 dpf(L, 0)
//    double dpf(int l, int u)
//    {
//        if (l <= 0) return 0.0;
//        if (vis[l][u]) return d[l][u];
//        vis[l][u] = 1;
//        double &ans = d[l][u];
//        ans = 0.0;
//        REP(i, m)
//        {
//            int c = idx(a[i]);
//            int v = ch[u][c];
//            if (val[v]) ans += b[c];
//            else ans += b[c] * dpf(l - 1, v);
//        }
//        return ans;
//    }

    ///不含的概率,最后1.0 - dpf(L, 0)
    double dpf(int l, int u)
    {
        if (l <= 0) return 1.0;
        if (vis[l][u]) return d[l][u];
        vis[l][u] = 1;
        double &ans = d[l][u];
        ans = 0.0;
        REP(i, m)
        {
            int c = idx(a[i]);
            int v = ch[u][c];
            if (!val[v]) ans += b[c] * dpf(l - 1, v);
        }
        return ans;
    }

}ac;

int main()
{
    while (cin >> m >> L && (m || L))
    {
        ac.init();
        REP(i, m)
        {
            scanf(" %c", &a[i]);
            scanf("%lf", &b[a[i] - 'a']);
        }
        RS(ca);
        ac.insert(ca, 1);
        ac.getFail();
        CLR(vis, 0);
//        ac.solve();
//        printf("%.2lf%%\n", (ac.dpf(L, 0)) * 100);
        printf("%.2lf%%\n", (1.0 - ac.dpf(L, 0)) * 100);
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值