zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    [记录]Python2.7使用argparse模块
    [记录]MySQL读写分离(Atlas和MySQL-proxy)
    [记录]Shell中的getopts和getopt用法
    [记录]CentOS搭建SVN服务器(主从同步)
    [记录]Zabbix3.4配置监控Oracle12c的存活状态和表空间使用率
    [记录]一则清理MySQL大表以释放磁盘空间的案例
    [原创]Oracle 12c的备份和恢复策略
    Linux awk用法
    Oracle数据库学习笔记
    oracle无法删除当前连接用户方法
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5753937.html
Copyright © 2011-2022 走看看