hdu3689 AC自动机Dp

来源:互联网 发布:视频人脸打马赛克软件 编辑:程序博客网 时间:2024/05/21 09:39

题目: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])周到自动机最后一个节点的概率总和。

提交情况:Accepted1

收获 the frist AC+dpprogram

ACcode

#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(intm){

   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;

}

 

原创粉丝点击