[JSOI2009]有趣的游戏

题意

给你一个字符串集

构造一个串 S, S , 每个位置你有 pi p i 的概率插入第 i i 个字符

问字符串集中每个字符串最先出现在构造的串中的概率


题解

涉及到字符串匹配首先想到建立 AC A C 自动机

考虑在 trie t r i e 图上 DP D P

f[u] f [ u ] 表示 u u 状态在 S S 中出现的概率

如果 u u 不是终止节点 , , 那么有

f[ch[u][i]]=f[u]×pi f [ c h [ u ] [ i ] ] = ∑ f [ u ] × p i

可以看出这个转移是成环的 , , 所以需要高斯消元

注意到所有字符串集中的字符串出现概率和为 1 1

idi i d i 表示第 i i 个字符串在 trie t r i e 图上的位置

if[id[i]]=1, ∑ i f [ i d [ i ] ] = 1 , 随意替换掉一个方程就可以了

注意特判 0.00 0.00

#include
#define fp(i,a,b) for(register int i=a,I=b+1;i
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define go(u) for(register int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
template<class T>inline bool cmax(T&a,const T&b){return a1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
char ss[1<<17],*A=ss,*B=ss;
inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
template<class T>inline void sd(T&x){
    char c;T y=1;while(c=gc(),(c<48||571)if(c==45)y=-1;x=c-48;
    while(c=gc(),4758)x=x*10+c-48;x*=y;
}
inline void Sd(char*s){char c;while(c=gc(),c<32);*s++=c;while(c=gc(),c>32)*s++=c;}
const int N=120;
const double eps=1e-12;
typedef int arr[N];
typedef double db;
int n,m,l;arr id;db p[N],ans[N],G[N][N];
struct ACAM{
    int Cnt,ch[N][26];arr ex,fail;char s[N];
    #define v (ch[u][i])
    inline int ins(){
        Sd(s);int u=0,i;
        fp(j,0,l-1)i=s[j]-'A',u=!v?v=++Cnt:v;
        ex[u]=1;return u;
    }
    inline void gf(){
        static int q[N];int u=0,i,h=1,t=0;
        fp(i,0,m)if(v)q[++t]=v;fail[0]=-1;
        while(h<=t)for(u=q[h++],i=0;i<=m;++i)v?fail[q[++t]=v]=ch[fail[u]][i]:v=ch[fail[u]][i];
    }
    inline void build(){
        fp(u,0,Cnt)G[u+1][u+1]=1;
        fp(u,0,Cnt)if(!ex[u])fp(i,0,m)G[v+1][u+1]-=p[i];
        fp(u,0,Cnt)G[1][u+1]=ex[u];G[1][Cnt+2]=1;
    }
    #undef v
}ac;
inline int cmp(db x){return fabs(x)0:x<0?-1:1;}
inline void Gauss(int n){
    db t;int mx;
    fp(i,1,n){mx=i;
        fp(j,i,n)if(fabs(G[mx][i])<fabs(G[j][i]))mx=j;
        if(mx^i)fp(j,i,n+1)swap(G[mx][j],G[i][j]);
        fp(j,i+1,n)if(cmp(G[j][i])){
            t=G[j][i]/G[i][i];
            fp(k,i,n+1)G[j][k]-=G[i][k]*t;
        }
    }
    fd(i,n,1){
        fp(j,i+1,n)G[i][n+1]-=G[i][j]*ans[j];
        ans[i]=G[i][n+1]/G[i][i];
    }
}
int main(){
    #ifndef ONLINE_JUDGE
        file("s");
    #endif
    sd(n),sd(l),sd(m);int a,b;--m;
    fp(i,0,m)sd(a),sd(b),p[i]=(db)a/b;
    fp(i,1,n)id[i]=ac.ins();
    ac.gf();ac.build();
    Gauss(ac.Cnt+1);
    fp(i,1,n)if(ans[id[i]+1]>0)printf("%.2lf\n",ans[id[i]+1]);else puts("0.00");
return 0;
}

你可能感兴趣的:(DP,概率期望,高斯消元,AC自动机)