2016 ACM/ICPC Asia Shenyang Station H - Guessing the Dice Roll HDU - 5955 ac automaton + probability dp + Gaussian elimination

http://acm.hdu.edu.cn/showproblem.php?pid=5955

The meaning of the question: give you n groups of length l, each number 1-6, throw a dice each time, ask you what is the probability of each string being matched for the first time

Problem solution: first build an ac automaton to construct a fail array, and then because the fail pointer may move forward, it cannot be directly recursive to dp. Gaussian elimination is required to solve the equation. For node i, it is assumed that it is not the end point and the point that can be transferred to it is a1,a2...an, then dp[i]=1/6*dp[a1]+1/6*dp[a2]+...+1/6*a[n] , then we can list n equations, Gaussian elimination and the probability of finding the end of each string is the answer

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double g=10.0,eps=1e-12;
const int N=100+10,maxn=20000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;

intl ;
double a[N][N],ans[N];
void gauss( intn )
{
    for(int i=1;i<n;i++)
    {
        if(a[i][i]==0)
        {
            int id=0;
            for(int j=i+1;j<=n;j++)
                if(a[j][i]!=0)
                    id=j;
            for(int j=i;j<=n+1;j++)
                swap(a[i][j],a[id][j]);
        }
        for(int j=i+1;j<=n;j++)
        {
            double t=a[j][i]/a[i][i];
            for(int k=i;k<=n+1;k++)
                a[j][k]-=(a[i][k]*t);
        }
    }
//    for(int i=1;i<=n;i++)
//    {
//        for(int j=1;j<=n+1;j++)
//            printf("%.12f ",a[i][j]);
//        puts("");
//    }
    for(int i=n;i>=1;i--)
    {
        for(int j=i+1;j<=n;j++)
            a[i][n + 1 ]-=ans[j]* a[i][j];
        ans[i]=a[i][n+1]/a[i][i];
    }
}
char s[N];
struct ACM{
    int root,tot;
    int Next[N][10],fail[N],End[N];
    int newnode()
    {
        memset(Next[tot],-1,sizeof Next[tot]);
        End [all] = 0 ;
        return all ++ ;
    }
    void init()
    {
        to = 0 ;
        root=newnode();
    }
    void ins(int i)
    {
        int now=root;
        for(int i=0,x;i<l;i++)
        {
            scanf("%d",&x);x--;
            if(Next[now][x]==-1)
                Next[now][x]=newnode();
            now=Next[now][x];
        }
        End[now]=i;
    }
    void build()
    {
        queue<int>q;
        fail[root]=root;
        for(int i=0;i<6;i++)
        {
            if(Next[root][i]==-1)Next[root][i]=root;
            else
            {
                fail[Next[root][i]]=root;
                q.push(Next[root][i]);
            }
        }
        while(!q.empty())
        {
            int now=q.front();
            q.pop();
            if(End[fail[now]])End[now]=End[fail[now]];
            for(int i=0;i<6;i++)
            {
                if(Next[now][i]==-1)Next[now][i]=Next[fail[now]][i];
                else
                {
                    fail[Next[now][i]]=Next[fail[now]][i];
                    q.push(Next[now][i]);
                }
            }
        }
    }
    void solve()
    {
        memset(a,0,sizeof a);
        a [ 1 ] [tot + 1 ] = - 1.0 ;
        for ( int i = 0 ; i <tot; i ++ )
        {
            a[i+1][i+1]=-1.0;
            if(End[i])continue;
            for(int j=0;j<6;j++)a[Next[i][j]+1][i+1]+=1.0/6;
        }
//        for(int i=1;i<=tot;i++)
//        {
//            for(int j=1;j<=tot+1;j++)printf("%.5f ",a[i][j]);
//            puts("");
//        }
        gauss(tot);
        bool ok=0;
        for(int i=0;i<tot;i++)
        {
            if(End[i])
            {
                if(!ok)printf("%.6f",ans[i+1]);
                else printf(" %.6f",ans[i+1]);
                ok=1;
            }
        }
        puts("");
    }
}ac;
intmain ()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        ac.init();
        int n;
        scanf("%d%d",&n,&l);
        for(int i=0;i<n;i++)ac.ins(i+1);
        ac.build();
        ac.solve();
    }
    return 0;
}
/***********************
1
2 2
1 1
2 1
***********************/
View Code

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325242507&siteId=291194637