UVA-11468 Substring(AC自动机+DP)
题目大意:给一些模板串,一些字符的出现概率。问不会出现模板串的概率是多少。
题目分析:是比较简单的概率DP+AC自动机。利用全概率公式递推即可。
代码如下:
# include<iostream> # include<cstdio> # include<queue> # include<cstring> # include<algorithm> using namespace std; const int N=1000; int ch[N+5][65]; int cnt; bool match[N+5]; int f[N+5]; char str[65][5]; double pi[65]; double dp[N+5][105]; bool vis[N+5][105]; void init() { cnt=0; memset(pi,0,sizeof(pi)); memset(ch,0,sizeof(ch)); memset(match,false,sizeof(match)); } int idx(char c) { if(c>='0'&&c<='9') return c-'0'; if(c>='a'&&c<='z') return c-'a'+10; return c-'A'+36; } void insert(string s) { int n=s.size(); int root=0; for(int i=0;i<n;++i){ int c=idx(s[i]); if(!ch[root][c]) ch[root][c]=++cnt; root=ch[root][c]; } match[root]=true; } void getFail() { queue<int>q; f[0]=0; for(int i=0;i<62;++i){ int u=ch[0][i]; if(!u) continue; f[u]=0; q.push(u); } while(!q.empty()) { int root=q.front(); q.pop(); for(int i=0;i<62;++i){ int u=ch[root][i]; if(!u){ ch[root][i]=ch[f[root]][i]; continue; } q.push(u); int v=f[root]; while(v&&!ch[v][i]) v=f[v]; f[u]=ch[v][i]; match[u]|=match[f[u]]; } } } double dfs(int u,int L) { if(vis[u][L]) return dp[u][L]; vis[u][L]=true; if(L==0) return dp[u][L]=1.0; double &ans=dp[u][L]; ans=0.0; for(int i=0;i<62;++i) if(!match[ch[u][i]]) ans+=pi[i]*dfs(ch[u][i],L-1); return ans; } int main() { //freopen("in.txt","r",stdin); int T,n,m,L,cas=0; scanf("%d",&T); while(T--) { init(); scanf("%d",&n); string p; for(int i=0;i<n;++i){ cin>>p; insert(p); } getFail(); scanf("%d",&m); double pp; for(int i=0;i<m;++i){ scanf("%s%lf",str[i],&pp); pi[idx(str[i][0])]=pp; } scanf("%d",&L); memset(vis,false,sizeof(vis)); printf("Case #%d: %.6lf\n",++cas,dfs(0,L)); } return 0; }