【uva11468-Substring】AC自动机+dp

http://acm.hust.edu.cn/vjudge/problem/31655

题意:给定k个模板串,n个字符以及选择它的概率pro[i],要构造一个长度问L的字符串s,问s不包含任意一个模板串的概率。

题解:

ed[i]标记trie上的点i是不是任意一个模板串的结尾(在求fail的时候ed[i]|=ed[i.fail])
d[i][l]表示从i出发还要走l步,构造的串不含模板串的概率,dp一下。注意清零。

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<queue>
  6 using namespace std;
  7 
  8 const int N=30,L=110,S=66;
  9 char s[L];
 10 int cnt[N*L];
 11 double d[N*L][L],pro[70];
 12 bool ed[N*L];
 13 queue<int> q;
 14 int num,k,n,l;
 15 struct node{
 16     int son[70];
 17     int fail;
 18 }a[N*L];
 19 
 20 int idx(char c)
 21 {
 22     if(c<='z' && c>='a') return c-'a'+1;
 23     if(c<='Z' && c>='A') return c-'A'+27;
 24     return c-'0'+53;
 25 }
 26 
 27 void clear(int x)
 28 {
 29     a[x].fail=0;
 30     memset(a[x].son,0,sizeof(a[x].son));
 31 }
 32 
 33 void trie(char *c)
 34 {
 35     int l=strlen(c);
 36     int x=0;
 37     for(int i=0;i<l;i++)
 38     {
 39         int t=idx(c[i]);
 40         if(!a[x].son[t])
 41         {
 42             num++;
 43             clear(num);
 44             a[x].son[t]=num;
 45         }
 46         x=a[x].son[t];
 47     }
 48     ed[x]=1;
 49 }
 50 
 51 void buildAC()
 52 {
 53     while(!q.empty()) q.pop();
 54     for(int i=1;i<=S;i++)
 55         if(a[0].son[i]) q.push(a[0].son[i]);
 56     while(!q.empty())
 57     {
 58         int x=q.front();q.pop();
 59         int fail=a[x].fail;
 60         for(int i=1;i<=S;i++)
 61         {
 62             int y=a[x].son[i];
 63             if(y)
 64             {
 65                 a[y].fail=a[fail].son[i];
 66                 ed[y]|=ed[a[fail].son[i]];
 67                 q.push(y);
 68             }
 69             else a[x].son[i]=a[fail].son[i];
 70         }
 71     }
 72 }
 73 
 74 double count(int x,int l)
 75 {
 76     if(l==0) return d[x][l]=1.0;
 77     if(d[x][l]!=-1) return d[x][l];
 78     d[x][l]=0;
 79     for(int i=1;i<=S;i++)
 80     {
 81         if(!pro[i]) continue;
 82         int y=a[x].son[i];
 83         if(!ed[y]) d[x][l]+=pro[i]*count(y,l-1);
 84     }
 85     return d[x][l];
 86 }
 87 
 88 int main()
 89 {
 90     freopen("a.in","r",stdin);
 91     freopen("a.out","w",stdout);
 92     int T,cas=0;
 93     scanf("%d",&T);
 94     while(T--)
 95     {
 96         num=0;
 97         clear(0);
 98         memset(cnt,0,sizeof(cnt));
 99         memset(ed,0,sizeof(ed));
100         memset(pro,0,sizeof(pro));
101         scanf("%d",&k);
102         for(int i=1;i<=k;i++)
103         {
104             scanf("%s",s);
105             trie(s);
106         }
107         buildAC();
108         scanf("%d",&n);getchar();
109         for(int i=1;i<=n;i++)
110         {
111             char c;
112             scanf("%c",&c);getchar();
113             scanf("%lf",&pro[idx(c)]);getchar();
114         }
115         scanf("%d",&l);
116         for(int i=0;i<=num;i++)
117             for(int j=0;j<=l;j++)
118                 d[i][j]=-1;
119         printf("Case #%d: %lf\n",++cas,count(0,l));
120     }
121     return 0;
122 }

 

posted @ 2016-07-19 22:01  拦路雨偏似雪花  阅读(220)  评论(0编辑  收藏  举报