【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 }