zoukankan      html  css  js  c++  java
  • BZOJ2553 Beijing2011禁忌(AC自动机+动态规划+矩阵快速幂+概率期望)

      考虑对一个串如何分割能取得最大值。那么这是一个经典的线段覆盖问题,显然每次取右端点尽量靠前的串。于是可以把串放在AC自动机上跑,找到一个合法串后就记录并跳到根。

      然后考虑dp。设f[i][j]表示前i位走到AC自动机上j节点的概率,枚举下个字符即可转移。同时记录此时期望伤害,找到合法串就统计入答案。

      并且注意到每次转移是相同的。矩阵快速幂优化即可。

      以及非常卡精度,需要全程long double。cout的保留小数位数误差是相当大的,必须用printf。并且转移到某个字符的概率即1/alphabet需要强制转换成long double,否则也会丢失精度。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 80
    #define double long double
    int n,m,S,trie[N][26],fail[N],val[N],q[N],cnt=0;
    char c[20];
    struct matrix
    {
        int n;double a[N][N];
        matrix operator *(const matrix&b) const
        {
            matrix c;c.n=n;memset(c.a,0,sizeof(c.a));
            for (int i=0;i<n;i++)
                for (int j=0;j<N;j++)
                    for (int k=0;k<N;k++)
                    c.a[i][j]+=a[i][k]*b.a[k][j];
            return c;
        }
    }f,a;
    void ins(char *a)
    {
        int n=strlen(a+1),t=0;
        for (int i=1;i<=n;i++)
        {
            if (!trie[t][a[i]-'a']) trie[t][a[i]-'a']=++cnt;
            t=trie[t][a[i]-'a'];
        }
        val[t]=1;
    }
    void build()
    {
        int head=0,tail=0;for (int i=0;i<S;i++) if (trie[0][i]) q[++tail]=trie[0][i];
        do
        {
            int x=q[++head];
            for (int i=0;i<S;i++)
            if (trie[x][i]) q[++tail]=trie[x][i],fail[trie[x][i]]=trie[fail[x]][i],val[trie[x][i]]|=val[fail[trie[x][i]]];
            else trie[x][i]=trie[fail[x]][i];
        }while (head<tail);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj2553.in","r",stdin);
        freopen("bzoj2553.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read(),S=read();
        for (int i=1;i<=n;i++) scanf("%s",c+1),ins(c);
        build();
        a.n=cnt+2;
        for (int i=0;i<=cnt;i++)
            for (int j=0;j<S;j++)
            if (val[trie[i][j]]) a.a[i][0]+=(double)1/S,a.a[i][cnt+1]+=(double)1/S;
            else a.a[i][trie[i][j]]+=(double)1/S;
        a.a[cnt+1][cnt+1]=1;
        f.n=1;f.a[0][0]=1;
        for (;m;a=a*a,m>>=1) if (m&1) f=f*a;
        printf("%.8Lf",f.a[0][cnt+1]);
        return 0;
    }
  • 相关阅读:
    Codeforces 451A Game With Sticks
    POJ 3624 Charm Bracelet
    POJ 2127 Greatest Common Increasing Subsequence
    POJ 1458 Common Subsequence
    HDU 1087 Super Jumping! Jumping! Jumping!
    HDU 1698
    HDU 1754
    POJ 1724
    POJ 1201
    CSUOJ 1256
  • 原文地址:https://www.cnblogs.com/Gloid/p/9581650.html
Copyright © 2011-2022 走看看