hdu3689 AC自动机Dp

本文介绍了一种使用AC自动机和动态规划算法解决特定概率问题的方法,详细解释了算法实现过程和应用实例,通过实例展示了解题步骤和关键思想。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3689

题目大意 :给定n个字符出现的概率,随机敲击m次,敲出的串中包含给定子串的概率

算法 AC自动机dp

思路 :建立AC自动机,设定状态f[step][k]表示第step步走到第kac自动机里的状态的概率,转移方程便是 f[step][k] = f[step – 1][trie[p].next[char]] * prob[trie[p].next[char]];最后的答案便是sumf[step][l])周到自动机最后一个节点的概率总和。

提交情况:Accepted 1

收获 the frist AC+dp program

AC code

#include <stdio.h>

#include <string.h>

#define MAXN (26)

#define MAXM (1010)

#define MAXL (20)

 

struct NODE{

    int next[MAXN];

    int falg;

    int suffix;

    int father;

}trie[MAXL * MAXN];

int ad;

charword[MAXL];

doubleprob[MAXN];

doublef[MAXM][MAXL];

intqueue[MAXL * MAXN], boo[MAXL * MAXN];

 

voidinsert(){

    int q = 0;

    for(int i = 0; word[i] != '\0'; i ++){

       if(trie[q].next[word[i] - 'a'] == -1){

           trie[q].next[word[i] - 'a'] = ad;

           trie[ad ++].father = q;

       }

       q = trie[q].next[word[i] - 'a'];

    }

    trie[q].falg = 1;

}

 

voidGet_trie_map(){

    int head, tail, i, opt, g, j;

    memset(boo, 0, sizeof(boo));

    head = tail = 0;

    trie[0].suffix = 0;

    boo[0] = 1;

    for(i = 0; i < MAXN; i ++)

       if(trie[0].next[i] == -1) trie[0].next[i] = 0;

       else trie[trie[0].next[i]].suffix = 0;

    queue[tail ++] = 0;

    while(head < tail){

       opt = queue[head ++];

       for(i = 0; i < MAXN; i ++)

           if(trie[opt].next[i] > opt && !boo[trie[opt].next[i]]){

              queue[tail ++] = g = trie[opt].next[i];

              boo[g] = 1;

              if(trie[g].suffix == -1) trie[g].suffix = trie[trie[opt].suffix].next[i];

              for(j = 0; j < MAXN; j ++)

                  if(trie[g].next[j] == -1) trie[g].next[j] = trie[trie[g].suffix].next[j];

           }

    }

}

voidBuilt_trie(){

    scanf("%s", word);

    ad = 1;

    memset(trie, -1, sizeof(trie));

    insert();

    Get_trie_map();

}

 

doubleGet_ans(int m){

    int i, j, k;

    double ans = 0;

    memset(f, 0, sizeof(f));

    f[0][0] = 1;

    for(i = 0; i < m; i ++)

       for(j = 0; j < ad - 1; j ++)

           if(i >= j)

              for(k = 0; k < MAXN; k ++){

                  int v = trie[j].next[k];

                  f[i + 1][v] += f[i][j] * prob[k];

              }

    for(i = 0; i <= m; i ++)

       ans += f[i][ad - 1];

    return ans;

}

 

int main(){

    int n, m, i;

    char ch[2];

    double pro, ans;

    while(~scanf("%d %d", &n, &m), n && m){

       memset(prob, 0, sizeof(prob));

       for(i = 0; i < n; i ++){

           scanf("%1s %lf", ch, &pro);

           prob[ch[0] - 'a'] = pro;

       }

       Built_trie();

       ans = Get_ans(m) * 100;

       printf("%.2lf%%\n", ans);

 

    }

    return 0;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值