zoukankan      html  css  js  c++  java
  • dtoj1721. 字符串生成器 ( strgen )

    1721. 字符串生成器 ( strgen )

    有一个字符串生成器,初始时生成的字符串为空串,它每次按照给定概率随机生成一个小写字母,加在当前已生成字符串的后面。

    给定N个长度为L的字符串,每个字符串由小写字母组成。
    如果在某个时候,发现每个给定字符串都在当前已生成的字符串中作为子串出现过,生成器就会停下来,将当前生成的字符串作为输出。
    求输出字符串长度的期望值。


    Sol

    考虑AC自动机。

    我们设f[k][S]表示当前走到的节点是k,已经完成的串为集合S,到最终状态的期望步数。

    那么可以发现f[k][S]是若干方程。

    我们按S分层,那么层与层之间的边是单向的,只有S连向S的子集。

    那么我们可以一层层高斯消元,对于跨层的边我们先算出上一层的答案,这层中当成常数就行。

    这题卡精!!!

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define maxn 55
    #define eps 1e-7
    using namespace std;
    int T,n,l,c,tr[maxn][10],tot,fail[maxn];
    int id[maxn];
    double p[10],a[maxn][maxn],f[maxn][1<<10],ans[maxn];
    char ch[maxn];
    void Q(){
        for(int i=0;i<=tot;i++){
            fail[i]=0;id[i]=0;
            for(int j=0;j<c;j++)tr[i][j]=0;
            for(int j=0;j<(1<<n);j++)f[i][j]=0;
        }
        tot=0;
    }
    bool ins(int x){
        int k=0;
        for(int i=0;i<l;i++){
            if(!tr[k][ch[i]-'a'])tr[k][ch[i]-'a']=++tot;
            k=tr[k][ch[i]-'a'];
        }
        if(id[k])return 0;
        id[k]=1<<(x-1);return 1;
    }
    queue<int>q;
    void build(){
        for(int i=0;i<c;i++)if(tr[0][i])q.push(tr[0][i]);
        while(!q.empty()){
            int k=q.front();q.pop();
            for(int i=0;i<c;i++){
                if(tr[k][i])fail[tr[k][i]]=tr[fail[k]][i],q.push(tr[k][i]);
                else tr[k][i]=tr[fail[k]][i];
            }
        }
    }
    void Guess(){
        int N=tot;
        for(int i=0;i<=N;i++){
            int Max=i;
            //for(int j=i;j<=N;j++)if(fabs(a[j][i])>fabs(a[Max][i]))Max=j;
            for(int j=i;j<=N+1;j++)swap(a[i][j],a[Max][j]);
            if(fabs(a[i][i])<eps)continue;
            for(int j=i+1;j<=N;j++){
                double tmp=a[j][i]/a[i][i];
                for(int k=i;k<=N+1;k++)a[j][k]-=a[i][k]*tmp;
            }
        }
        for(int i=N;i>=0;i--){
            ans[i]=-a[i][N+1]/a[i][i];
            for(int j=i-1;j>=0;j--){
                a[j][N+1]+=a[j][i]*ans[i];
            }
        }
    }
    void work(){
        Q();
        scanf("%d%d%d",&n,&l,&c);
        for(int i=1;i<=n;i++){
            scanf(" %s",ch);
            if(!ins(i))n--,i--;
        }
        build();
        for(int i=0,t;i<c;i++){
            scanf("%d",&t);p[i]=1.0*t/10000;
            
        }
        int N=(1<<n)-1; 
        
        for(int S=N-1;S>=0;S--){
            for(int i=0;i<=tot;i++)
            for(int j=0;j<=tot+1;j++)a[i][j]=0;
            for(int i=0;i<=tot;i++){
                for(int j=0;j<c;j++){
                    int v=tr[i][j];
                    a[i][v]+=p[j];
                    if(id[v]&&(!(S&id[v]))){
                        a[i][v]-=p[j];
                        a[i][tot+1]+=(f[v][S|id[v]])*p[j];
                    }
                }
                a[i][i]--;a[i][tot+1]++;
            }
            Guess();
            for(int i=0;i<=tot;i++)f[i][S]=ans[i];
        }
        printf("%.5lf
    ",f[0][0]);
    }
    int main(){
        for(scanf("%d",&T);T--;work());
        return 0;
    }
    View Code
  • 相关阅读:
    slf4j绑定log4j失败
    [转]activiti5用户任务分配
    关于ajax提交的公共接口的一大用处
    jQuery插件开发方式
    centos7安装mysql
    Centos7安装JDK
    奇葩问题:spring+mybaits项目突然出现其中一些Mapper类找不到
    JAVA多线程下,获取递增的序列号
    库存扣减的流水账记录问题
    My97DatePicker使用的问题
  • 原文地址:https://www.cnblogs.com/liankewei/p/12251823.html
Copyright © 2011-2022 走看看