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
",++cas,dfs(0,L));
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/20143605--pcx/p/5753937.html