zoukankan      html  css  js  c++  java
  • UVA 11468 Substring

      题目大意:给出n种字符和其出现的概率,给出一些模板串,求随机生成长度为L的串中不含任意模板串作为子串的概率。模板串个数≤20,串长≤20,L≤100。    

      这么多个模板串肯定是AC自动机。

      不出现任意一个模板串,即走不到AC自动机上val有值(标为单词结尾)的点。

      随机生成长度为L的字符串,即在AC自动机上随机走L步。

      处理方法是记忆化搜索。设g(x,step)表示当前在AC自动机的点x上、还需要走step步,走不到结尾点的概率。那么答案就是g(0,L)。

      那么转移根据全概率公式(感性证明)就是

      

      能转移当且仅当ch[x][i]不是一个串的结尾。

      边界条件是g(x,0)=1。

    #include    <iostream>
    #include    <cstdio>
    #include    <cstdlib>
    #include    <algorithm>
    #include    <vector>
    #include    <cstring>
    #include    <queue>
    #include    <complex>
    #include    <stack>
    #define LL long long int
    #define dob double
    #define FILE "11468"
    using namespace std;
    
    const int N = 1010;
    const int M = 71;
    int n,L,K,tot,ch[N][M],id[N],val[N],fail[N];
    double P[N][N],pro[N];
    bool vis[N][N];
    char S[N][N],g[M];
    
    inline int gi(){
      int x=0,res=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')res*=-1;ch=getchar();}
      while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
      return x*res;
    }
    
    inline void insert(char *s,int rt=0){
      for(int i=0,j=strlen(s);i<j;++i){
        int x=id[s[i]];
        if(!ch[rt][x]){
          ch[rt][x]=++tot;val[tot]=0;
          memset(ch[tot],0,sizeof(ch[tot]));
        }
        rt=ch[rt][x];
      }
      val[rt]=1;
    }
    
    inline void getfail(){
      queue<int>Q;fail[0]=val[0]=0;
      for(int i=1;i<=n;++i){
        int y=ch[0][i];
        if(y)fail[y]=0,Q.push(y);
      }
      while(!Q.empty()){
        int x=Q.front();Q.pop();
        for(int i=1;i<=n;++i){
          int y=ch[x][i];
          if(!y){
            ch[x][i]=ch[fail[x]][i];
            continue;
          }
          Q.push(y);int z=fail[x];
          while(z && ch[z][i]==0)z=fail[z];
          fail[y]=ch[z][i];val[y]|=val[fail[y]];
        }
      }
    }
    
    inline double getprob(int x,int step){
      if(!step)return 1.0;
      if(vis[x][step])return P[x][step];
      vis[x][step]=1;double ans=0.0;
      for(int i=1;i<=n;++i)
        if(!val[ch[x][i]])
          ans+=pro[i]*getprob(ch[x][i],step-1);
      return P[x][step]=ans;
    }
    
    inline void solve(){
      K=gi();tot=0;
      memset(ch[0],0,sizeof(ch[0]));
      memset(vis,0,sizeof(vis));
      for(int i=1;i<=K;++i)scanf("%s",S[i]);
      n=gi();memset(id,0,sizeof(id));
      for(int i=1;i<=n;++i){
        scanf("%s%lf",g,&pro[i]);
        id[g[0]]=i;
      }
      for(int i=1;i<=K;++i)insert(S[i]);
      getfail();L=gi();
      double ans=getprob(0,L);
      printf("%.6lf
    ",ans);
    }
    
    int main()
    {
      freopen(FILE".in","r",stdin);
      freopen(FILE".out","w",stdout);
      int Case=gi();
      for(int t=1;t<=Case;++t){
        printf("Case #%d: ",t);
        solve();
      }
      fclose(stdin);fclose(stdout);
      return 0;
    }
    Substring
  • 相关阅读:
    在线文件转换工具
    中鸣机器人官网
    下载tortoisegit
    知晓云,不用申请服务器即可完成小程序后台开发和部署
    全网音乐免费下载工具
    MySQL5.7 主从复制配置
    Nginx-------Nginx的安装和多域名配置
    如何获取域名(网址)对应的IP地址
    LOGO免费在线设计
    Jmeter-----保存到响应文件
  • 原文地址:https://www.cnblogs.com/fenghaoran/p/7695170.html
Copyright © 2011-2022 走看看