Substring Uva 11468_记忆化搜索 + AC自动机
Code:
#include<cstdio> #include<cstring> #include<queue> using namespace std; const int maxn=100; const int maxd=400+3; const int sigma=65; double d[maxd][103],perc[sigma+3]; int ch[maxd][sigma+1],end1[maxd],f[maxd],last[maxd]; char A[30],mapp[sigma+3]; int cnt; queue<int>Q; int idx(char s){ if(s>='a'&&s<='z')return s-'a'; if(s>='A'&&s<='Z')return s-'A'+26; return s-'0'+52; } struct V { void insert(char p[]){ int n=strlen(p); int cur=0; for(int i=0;i<n;++i){ int c=idx(p[i]); if(!ch[cur][c])ch[cur][c]=++cnt; cur=ch[cur][c]; } end1[cur]=1,last[cur]=1; } void getfail(){ for(int i=0;i<sigma;++i)if(ch[0][i])Q.push(ch[0][i]); while(!Q.empty()){ int r=Q.front();Q.pop(); for(int i=0;i<sigma;++i){ int u=ch[r][i]; if(!u){ch[r][i]=ch[f[r]][i];continue;} Q.push(u); int v=f[r]; while(v&&!ch[v][i])v=f[v]; f[u]=ch[v][i]; if(last[f[u]])last[u]=1; } } } double dp(int j,int L,int l,int n){ if(end1[j]||last[j])return 0.0; if(L==l)return 1.0; if(d[j][L]>=0)return d[j][L]; double ans=0.0; for(int i=1;i<=n;++i){ int c=idx(mapp[i]); ans+=perc[i]*dp(ch[j][c],L+1,l,n); } d[j][L]=ans; return ans; } }AC; int main(){ int T;scanf("%d",&T); for(int cas=1;cas<=T;++cas) { memset(end1,0,sizeof(end1)); memset(d,-1,sizeof(d)); memset(f,0,sizeof(f)); memset(last,0,sizeof(last)); memset(ch,0,sizeof(ch)); cnt=0; int k;scanf("%d",&k); for(int i=1;i<=k;++i){scanf("%s",A);AC.insert(A);} int n;scanf("%d",&n);char g=getchar(); for(int i=1;i<=n;++i) {scanf("%c",&mapp[i]); scanf("%lf",&perc[i]);g=getchar();} int l;scanf("%d",&l); AC.getfail(); double ans=AC.dp(0,0,l,n); printf("Case #%d: ",cas); printf("%.6f\n",ans); } return 0; }