WHU 1572 Cyy and Fzz(AC自動機+dp)

題意:給出n個模板串,隨機一個串,求出現模板串個數的期望(相同算一個)。

做法:比賽時誤以爲是求模板串出現了幾次,用dp[i][j]代表在第i個節點還要走l步的期望,然後記憶化搜索。。不停的wa。。

後來問了別人才知道是看錯題目了。做法應該是先求概率,再求期望,用dp[i][j][k]表示走了i步,停在j節點,得到串集合爲k的概率。

最後答案就是sum(dp[i][j][k]*(k裏串的個數))。

AC代碼:

<span style="font-size:14px;">//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<string.h>
#include<string>
#include<sstream>
#include<bitset>
using namespace std;
#define ll long long
#define ull unsigned long long
#define eps 1e-8
#define NMAX 900000
#define MOD 1000000007
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI acos(-1)
#define mp make_pair
template<class T>
inline void scan_d(T &ret)
{
    char c;
    int flag = 0;
    ret=0;
    while(((c=getchar())<'0'||c>'9')&&c!='-');
    if(c == '-')
    {
        flag = 1;
        c = getchar();
    }
    while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
    if(flag) ret = -ret;
}
const int maxnode = 10*12;

struct AhoCorasick
{
    int ch[maxnode][26];
    int f[maxnode];
    int val[maxnode];
    int sz;
    void clear()
    {
        memset(ch[0],0,sizeof(ch[0]));
        memset(val,0,sizeof(val));
        sz = 1;
    }
    int idx(char c)
    {
        return c-'a';
    }
    void insert(char *s, int v)
    {
        int u = 0, n = strlen(s);
        for(int i = 0; i < n; i++)
        {
            int c = idx(s[i]);
            if(!ch[u][c])
            {
                memset(ch[sz],0,sizeof(ch[sz]));
                val[sz] = 0;
                ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
        val[u] |= (1<<v);
    }
    void getFail()
    {
        queue<int>q;
        f[0] = 0;
        for(int c = 0; c < 26; c++)
        {
            int u = ch[0][c];
            if(u)
            {
                f[u] = 0; q.push(u);
            }
        }
        while(!q.empty())
        {
            int r = q.front(); q.pop();
            for(int c = 0; c < 26; c++)
            {
                int u = ch[r][c];
                if(!u)
                {
                    ch[r][c] = ch[f[r]][c];
                    continue;
                }
                q.push(u);
                int v = f[r];
                while(v && !ch[v][c]) v = f[v];
                f[u] = ch[v][c];
                val[u] |= val[f[u]];
            }
        }
    }
}ac;
double dp[16][maxnode][1<<8];

int ge[1<<8];
int n,l;

char s[20];//1 14 a 0.422525
int main()
{
#ifdef GLQ
    freopen("input.txt","r",stdin);
//    freopen("o1.txt","w",stdout);
#endif // GLQ
    int cas,pp = 0;
    for(int i = 0; i < (1<<8); i++)
    {
        ge[i] = 0;
        for(int j = 0; j < 8; j++) if(i&(1<<j)) ge[i]++;
    }
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d%d",&n,&l);
        ac.clear();
        for(int i = 0; i < n; i++)
        {
            scanf("%s",s);
            ac.insert(s,i);
        }
        ac.getFail();
        memset(dp,0,sizeof(dp));
        dp[0][0][0] = 1;
        for(int i = 0; i < l; i++)
            for(int j = 0; j < ac.sz; j++)
                for(int k = 0; k < (1<<n); k++) if(dp[i][j][k])
                    for(int x = 0; x < 26; x++)
                    {
                        int next = ac.ch[j][x];
                        dp[i+1][next][k|ac.val[next]] += dp[i][j][k]/26.0;
                    }

        double ans = 0;
        for(int i = 0; i < ac.sz; i++)
            for(int j = 0; j < (1<<n); j++)
            {
                ans += dp[l][i][j]*ge[j];
            }
        printf("%.6lf\n",ans);
    }
    return 0;
}
</span>


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章