题目链接
题解
我保证如果我自己想这道题起码要想一个星期,因为学了AC自动机完全不会用,woc而且每次都要忘记调用getfail QAQ也是够了.
乍一看有很多模板,就用字典树吧,随机一个字母就相当于走一步嘛,就相当于不断在匹配你生成的这个字符串.涉及到匹配和多模板问题当然就是AC自动机了.这里要用改造后的AC自动机(就是不用顺着fail找的那种).不包含任何一个模板,就要求不到任何一个单词节点,用val表示这个点能走否到,注意在getfail的时候要 val[i] |= val[f[i]] ,也就是说到这里的时候生成串里某个后缀可能是某个模板.然后记忆化搜索,dp[i][j]表示在i这个节点还要走j步的可能性.
代码
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxl=100+10;
const int maxnode=500;
const int sigma_size=64;
int idxx[maxl];
double dp[maxnode][maxl],prob[sigma_size];
int n,m,l;
int idx(char ch){
if(ch>='a'&&ch<='z')return ch-'a';
if(ch>='A'&&ch<='Z')return ch-'A'+26;
return ch-'0'+26*2;
}
struct AC_auto{
int sz,val[maxnode];
int ch[maxnode][sigma_size];
void clear(){
sz=1;
memset(ch[0],0,sizeof(ch[0]));
memset(dp,0,sizeof(dp));
memset(prob,0,sizeof(prob));
memset(vis,0,sizeof(vis));
}
void insert(char *T,int v){
int n=strlen(T),u=0;
for(int i=0;i<n;i++)
{
int c=idx(T[i]);
if(!ch[u][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]=v;
return ;
}
int f[maxnode];
void getfail()
{
queue<int>q;
f[0]=0;
for(int c=0;c<sigma_size;c++)
{
int x=ch[0][c];
if(x) q.push(x),f[x]=0;
}
while(!q.empty())
{
int r=q.front();q.pop();
for(int c=0;c<sigma_size;c++)
{
int u=ch[r][c];
if(!u){
ch[r][c]=ch[f[r]][c];continue;
}
q.push(u);
int v=f[r];
while(v&&!ch[v][c]) v=f[v];
f[u]=ch[v][c];
val[u] |= val[f[u]];
}
}
}
int vis[maxnode][maxl];
double getprob(int u,int l)
{
if(!l) return 1.0;
if(vis[u][l])
return dp[u][l];
vis[u][l]=1;
double &ans=dp[u][l];//****** &
ans=0.0;
for(int c=1;c<=m;c++)
if(!val[ch[u][idxx[c]]])
ans+=prob[c]*getprob(ch[u][idxx[c]],l-1);
return ans;
}
}ac;
int kase=0;
char T[maxl],t[9];
void solve()
{
ac.clear();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",T);ac.insert(T,1);
}
ac.getfail();
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%s",t);scanf("%lf",&prob[i]);idxx[i]=idx(t[0]);
}
scanf("%d",&l);
printf("Case #%d: %.6lf\n",++kase,ac.getprob(0,l));
return ;
}
int main()
{
int T;cin>>T;
while(T--) solve();
return 0;
}