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, that’s not what is asked here. J
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, pi. 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
· ∑pi = 1
· L ≤ 100
Sample Input Output for Sample Input
2 1 a 2 a 0.5 b 0.5 2
2 ab ab 2 a 0.2 b 0.8 2 | Case #1: 0.250000 Case #2: 0.840000 |
题意:给出一些字符和各自的选择概率,随机选择L次后将得到一个长度为L的随机字符串S,给出K个模板串,计算S不包含任何一个串的概率(即任何一个模板串都不是S的连续子串)
思路:AC自动机+DP。首先将所给病毒串建立trie图。末尾+上标记。然后DP转移为
dp[i+1] = dp[qq[j] -> next[k] -> cnt] += dp[i][j] * p[k];
即长度为I,当前状态为J,后面添加一个字符转移到的状态的概率为dp[i][j]的概率乘于该字符的概率。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 15000
int Cnt = 0;
double dp[108][500];
double p[68];
struct node
{
node * fail;
node * next[62];
int cnt,end;
node()
{
fail = NULL;
for(int i = 0;i < 62;i++)
next[i] = NULL;
cnt = Cnt++;
end = 0;
}
}*q[maxn],*qq[maxn];
char str[28];
int first,rear;
int idx(char c)
{
if(c >= 'a' && c <= 'z') return c - 'a';
if(c >= 'A' && c <= 'Z') return c - 'A' + 26;
return c - '0' + 52;
}
void Creat_Trie(char * s,node * root)
{
int i,id,len;
node * p = root;
len = strlen(s);
for(int i = 0;i < len;i++)
{
if(p -> end) break;
id = idx(s[i]);
if(p -> next[id] == NULL)
p -> next[id] = qq[Cnt-1] = new node();
p = p -> next[id];
}
p -> end = 1;
}
void Build_ac_automation(node * root)
{
q[rear++] = root;
node * p = NULL;
while(first < rear)
{
p = q[first++];
for(int i = 0;i < 62;i++)
{
if(p -> next[i] != NULL)
{
if(p == root)
{
p -> next[i] -> fail = root;
}
else
{
p -> next[i] -> fail = p -> fail -> next[i];
if(p -> fail -> next[i] -> end)
p -> next[i] -> end = 1;
}
q[rear++] = p -> next[i];
}
else
{
if(p == root)
{
p -> next[i] = root;
}
else
{
p -> next[i] = p -> fail -> next[i];
}
}
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
for(int cas = 1;cas <= t;cas++)
{
first = rear = Cnt = 0;
node * root = new node();
qq[0] = root;
int k; scanf("%d",&k);
while(k--)
{
scanf("%s",str);
Creat_Trie(str,root);
}
Build_ac_automation(root);
int n; scanf("%d",&n);
memset(p,0,sizeof(p));
for(int j = 1;j <= n;j++)
{
char c; cin >> c;
double pp; scanf("%lf",&pp);
p[idx(c)] = pp;
}
int L; scanf("%d",&L);
memset(dp,0,sizeof(dp));
dp[0][0] = 1;
for(int i = 0;i < L;i++)
{
for(int j = 0;j < Cnt;j++)
{
if(qq[j] -> end) continue;
for(int k = 0;k < 62;k++)
{
if(p[k] != 0 && qq[j] -> next[k] -> end == 0)
{
dp[i+1][qq[j] -> next[k] -> cnt] += dp[i][j] * p[k];
}
}
}
}
double ans = 0;
for(int i = 0;i < Cnt;i++)
{
if(qq[i] -> end == 0)
ans += dp[L][i];
}
printf("Case #%d: %.6lf\n",cas,ans);
}
return 0;
}