hdu2825——ac自动机,DP

来源:互联网 发布:perl json 格式化输出 编辑:程序博客网 时间:2024/05/17 02:22

题意:求长度为n,至少包含了给定字符串k个的字符串有多少种。

还是多段图递推的思想,不过这一次是在ac自动机上,用10个二进制位表示已经出现的字符串。

#include <iostream>#include <cstring>#include <cstdio>#include <queue>using namespace std;const int maxn = 1000 + 10;const int mod = 20090717;int n, m, k;int bit_count(int num) { return num == 0 ? 0 : (num & 1) + bit_count(num / 2); }struct ac_automaton{    int ch[maxn][30], val[maxn];    int f[maxn], last[maxn], sz;    int dp[105][27][(1 << 10) + 10];    void init()    {        sz = 1; memset(ch, 0, sizeof(ch));        memset(val, 0, sizeof(val)); memset(f, 0, sizeof(f));        memset(last, 0, sizeof(last));        memset(dp, 0, sizeof(dp));    }    void insert(char * s, int v)    {        int u = 0;        for(int i = 0; s[i]; ++i)        {            int c = s[i] - 'a';            if(!ch[u][c])            {                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); last[u] = 0; }            else ch[0][c] = 0;        }        while(!q.empty())        {            int r = q.front(); q.pop();            for(int c = 0; c < 26; ++c)            {                int u = ch[r][c];                if(u)                {                    q.push(u);                    int p = f[r];                    while(p && ch[p][c] == 0) p = f[p];                    f[u] = ch[p][c]; last[u] = val[f[u]] ? f[u] : last[f[u]];                    val[u] |= val[last[u]];                }                else ch[r][c] = ch[f[r]][c];            }        }    }    int slove()    {        dp[0][0][0] = 1;        for(int l = 0; l < n; ++l)        {            for(int u = 0; u < sz; ++u)            {                for(int s = 0; s < (1 << m); ++s)                {                    if(dp[u][l][s] == 0) continue;                    for(int c = 0; c < 26; ++c)                    {                        int v = ch[u][c];                        dp[v][l + 1][s | val[v]] += dp[u][l][s];                        dp[v][l + 1][s | val[v]] %= mod;                    }                }            }        }        int res = 0;        for(int i = 0; i < sz; ++i)        {            for(int j = 0; j < (1 << m); ++j)            {                if(bit_count(j) >= k)                {                    res += dp[i][n][j];                    res %= mod;                }            }        }        return res;    }}a;int main(){    freopen("in", "r", stdin);    while(~scanf("%d %d %d", &n, &m, &k))    {        if(n == 0 && m == 0 && k == 0) break;        a.init();        for(int i = 0; i < m; ++i)        {            char str[100];            scanf("%s", str);            a.insert(str, i);        }        a.getFail();        printf("%d\n", a.slove());    }    return 0;}


原创粉丝点击