题目意思:给出k个模式串,然后随机生成一个长度为L字符串,每个字符被选中的概率为pi 。 问构造出来的字符串不包含任何模式串的概率。
分析:显然这是一个模式串的母串的匹配,显然需要先构建一个AC自动机。我们用dp[i][j] 表示当前正在构造第i个字符,fail指针在j节点上能构造成功的概率。那么我们可以顺着fail指针向后面的状态。 注意只能扩展有效状态,也即不包含任何模式串的状态。 也即
dp [i][j]->dp[i+1][ch[j][k] ]; ch[j][k] 表示如果选k字符的话的下一状态。
VIEW CODE
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<cstring>
#include<map>
#include<vector>
#include<set>
#include<ctime>
#include<stdlib.h>
using namespace std;
const int mmax=2100;
struct AC_trie
{
double dp[110][mmax];
int ch[mmax][63];
int cnt[mmax],Fail[mmax],match[mmax];
int num,k,L,n;
char patter[30];
double p[70];
int get_id(char c)
{
if('0'<=c && c<='9')
return c-'0';
if('A'<=c && c<='Z')
return c-'A'+10;
if('a'<=c && c<='z')
return c-'a'+36;
return 0;
}
void init()
{
memset(ch,0,sizeof ch);
memset(match,0,sizeof match);
memset(cnt,0,sizeof cnt);
cnt[0]=0;
num=0;
memset(p,0,sizeof p);
memset(dp,0,sizeof dp);
}
void read(int n)
{
for(int i=0;i<n;i++)
{
scanf("%s",patter);
Insert(patter);
}
}
int newnode()
{
num++;
memset(ch[num],0,sizeof ch[num]);
cnt[num]=0;
return num;
}
void Insert(char *s)
{
int u=0;
for(int i=0;s[i];i++)
{
if(!ch[u][get_id(s[i])])
ch[u][get_id(s[i])]=newnode();
u=ch[u][get_id(s[i])];
}
cnt[u]++;
match[u]=1;
}
void get_Fail()
{
queue<int>q;
Fail[0]=0;
for(int i=0;i<62;i++)
{
int u=ch[0][i];
if(u)
{
q.push(u);
Fail[u]=0;
}
}
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=0;i<62;i++)
{
int u=ch[x][i];
if(!u)
{
ch[x][i]=ch[Fail[x]][i];
continue;
}
q.push(u);
int v=Fail[x];
while(v && !ch[v][i]) v=Fail[v];
Fail[u]=ch[v][i];
match[u] |=match[Fail[u]];
}
}
}
void work()
{
init();
scanf("%d",&k);
read(k);
scanf("%d",&n);
for(int i=0;i<n;i++)
{
char xx[2];
double dd;
scanf("%s %lf",xx,&dd);
p[get_id(xx[0])]=dd;
}
scanf("%d",&L);
get_Fail();
dp[0][0]=1.0;
for(int i=0;i<L;i++)
{
for(int j=0;j<=num;j++)
{
if(!match[j])
for(int k=0;k<62;k++)
dp[i+1][ch[j][k] ]+=dp[i][j]*p[k];
}
}
double ans=0.0;
for(int i=0;i<=num;i++)
if(!match[i]) ans+=dp[L][i];
printf("%.6lf\n",ans);
}
}Ac;
int main()
{
int t,ca=0;
//freopen("in.txt","r",stdin);
cin>>t;
while(t--)
{
printf("Case #%d: ",++ca);
Ac.work();
}
return 0;
}