UVA_11468_Substring_(AC自动机+概率动态规划)
描述
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2463
给出一些子串.然后给出一些字符,以及每个字符出现的概率.现在用这些字符组成一个长度为s的字符串,问之前给出的子串都没有在这个字符串中出现的概率是多少.
分析
边选字母边匹配.只要前面的字串都不能匹配成功即可.用前面的那些子串造出个AC自动机,然后在上面跑.用match数组表示每个点是否是单词节点,根据题意,只要不是单词节点都可以跑.然后AC自动机在get_fail的时候把没有的边补上.
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxt=50+5,maxk=20+5,maxl=100+5,maxnode=20*20+5,type=26+26+10; 5 int t,k,l,n,kase; 6 char p[maxk][20]; 7 double pro[type]; 8 inline int idx(char c){ 9 if(c>='0'&&c<='9') return c-'0'; 10 if(c>='a'&&c<='z') return c-'a'+10; 11 return c-'A'+36; 12 } 13 struct Aho_Corasick{ 14 int ch[maxnode][type]; 15 int f[maxnode]; 16 double dp[maxnode][maxl]; 17 bool match[maxnode]; 18 int sz; 19 void init(){ 20 sz=1; 21 match[0]=false; 22 memset(pro,0,sizeof pro); 23 memset(ch[0],0,sizeof ch[0]); 24 memset(dp,-1,sizeof dp); 25 } 26 void insert(char *s){ 27 int u=0; 28 for(;*s;s++){ 29 int c=idx(*s); 30 if(!ch[u][c]){ 31 memset(ch[++sz],0,sizeof ch[sz]); 32 match[sz]=false; 33 ch[u][c]=sz; 34 } 35 u=ch[u][c]; 36 } 37 match[u]=true; 38 } 39 void get_fail(){ 40 queue <int> q; 41 f[0]=0; 42 for(int c=0;c<type;c++){ 43 int u=ch[0][c]; 44 if(u){ f[u]=0; q.push(u); } 45 } 46 while(!q.empty()){ 47 int r=q.front(); q.pop(); 48 for(int c=0;c<type;c++){ 49 int u=ch[r][c]; 50 if(!u){ ch[r][c]=ch[f[r]][c]; continue; } 51 q.push(u); 52 int v=f[r]; 53 f[u]=ch[v][c]; 54 match[u]|=match[f[u]]; 55 } 56 } 57 } 58 double get_pro(int u,int l){ 59 if(!l) return 1.0; 60 if(dp[u][l]>=0) return dp[u][l]; 61 double &ans=dp[u][l]; 62 ans=0.0; 63 for(int c=0;c<type;c++)if(!match[ch[u][c]]) ans+=pro[c]*get_pro(ch[u][c],l-1); 64 return ans; 65 } 66 }ac; 67 int main(){ 68 scanf("%d",&t); 69 while(t--){ 70 ac.init(); 71 scanf("%d",&k); 72 for(int i=1;i<=k;i++){ 73 scanf("%s",p[i]); 74 ac.insert(p[i]); 75 } 76 ac.get_fail(); 77 scanf("%d",&n); 78 for(int i=1;i<=n;i++){ 79 char c; 80 while(c=getchar(),c=='\n'); 81 scanf("%lf",&pro[idx(c)]); 82 } 83 scanf("%d",&l); 84 printf("Case #%d: %lf\n",++kase,ac.get_pro(0,l)); 85 } 86 return 0; 87 }
11468
Substring
Given a set of pattern strings, and a text, you have to find, if any of the pattern is a substring of the
text. If any of the pattern string can be found in text, then print ‘yes’, otherwise ‘no’ (without quotes).
But, unfortunately, thats not what is asked here.
The problem described above, requires a input file generator. The generator generates a text of
length L, by choosing L characters randomly. Probability of choosing each character is given as priori,
and independent of choosing others.
Now, given a set of patterns, calculate the probability of a valid program generating “no”.
Input
First line contains an integer T , the number of test cases. Each case starts with an integer K, the
number of pattern strings. Next K lines each contain a pattern string, followed by an integer N ,
number of valid characters. Next N lines each contain a character and the probability of selecting that
character, p i . Next an integer L, the length of the string generated. The generated text can consist of
only the valid characters, given above.
There will be a blank line after each test case.
Output
For each test case, output the number of test case, and the probability of getting a “no”.
Constraints:
• T ≤ 50
• K ≤ 20
• Length of each pattern string is between 1 and 20
• Each pattern string consists of only alphanumeric characters (a to z, A to Z, 0 to 9)
• Valid characters are all alphanumeric characters
•
∑
p i = 1
• L ≤ 100
Sample Input
2
1
a
2
a 0.5
b 0.5
2
2
ab
2
a 0.2
b 0.8
2
Sample Output
Case #1: 0.250000
Case #2: 0.840000