• [HDU2825]Wireless Password


    题意:给定$m$个字符串,要求你求出长度为$n$,且至少包含$m$个字符串中的$K$串的字符串的方案数。

    题解:这题的$m$很小,只有10,所以可以考虑状压DP,先对这$m$个串构建AC自动机,然后设$f[i][j][s]$表示长度为$i$,目前在自动机上的节点是$j$,与这$m$个字符串匹配的情况是$s$的方案数,然后依赖AC自动机转移。


    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <bitset>
    using namespace std;
    #define reg register
    inline int read() {
        int res = 0;char ch=getchar();bool fu=0;
        while(!isdigit(ch))fu|=(ch=='-'),ch=getchar();
        while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
        return fu?-res:res;
    }
    #define mod 20090717
    int n, m, K;
    int bin[11];
    int nxt[105][26], fail[105], danger[105], tot;
    
    inline void ins(char *str, int id)
    {
        int len = strlen(str + 1);
        int now = 0;
        for (reg int i = 1 ; i <= len ; i ++)
            now = nxt[now][str[i]-'a'] ? nxt[now][str[i]-'a'] : nxt[now][str[i]-'a'] = ++tot;
        danger[now] |= bin[id - 1];
    }
    
    inline void Build()
    {
        queue <int> q;
        for (reg int i = 0 ; i < 26 ; i ++) if (nxt[0][i]) q.push(nxt[0][i]);
        while(!q.empty())
        {
            int x = q.front();q.pop();
            for (reg int i = 0 ; i < 26 ; i ++)
                if (nxt[x][i]) fail[nxt[x][i]] = nxt[fail[x]][i], q.push(nxt[x][i]);
                else nxt[x][i] = nxt[fail[x]][i];
            danger[x] |= danger[fail[x]];
        }
    }
    
    int f[26][105][1<<10];
    
    int main()
    {
        bin[0] = 1;
        for(reg int i=1;i<=10;i++) bin[i]=bin[i-1]<<1;
        while(1)
        {
            n = read(), m = read(), K = read();
            if (!n and !m and !K) return 0;
            memset(nxt, 0, sizeof nxt), memset(fail, 0, sizeof fail);
            memset(danger, 0, sizeof danger);
            tot = 0;
            char str[15];
            for (reg int i = 1 ; i <= m ; i ++)
            {
                scanf("%s", str + 1);
                ins(str, i);
            }
            Build();
            memset(f, 0, sizeof f);
            f[0][0][0] = 1;
            for (reg int i = 0 ; i < n ; i ++)
            {
                for (reg int j = 0 ; j <= tot ; j ++)
                {
                    for (reg int s = 0 ; s < bin[m] ; s ++)
                    {
                        if (!f[i][j][s]) continue;
                        for (reg int p = 0 ; p < 26 ; p ++)
                        {
                            int to = nxt[j][p], sit = s | danger[to];
                            f[i + 1][to][sit] = (f[i + 1][to][sit] + f[i][j][s]) % mod;
                        }
                    }
                }
            }
            bitset <11> bit;
            int ans = 0;
            for (reg int s = 0 ; s < bin[m] ; s ++)
            {
                bit = s;
                if ((signed)bit.count() >= K) {
                    for (reg int j = 0 ; j <= tot ; j ++)
                        (ans += f[n][j][s]) %= mod;
                }
            }
            printf("%d
    ", ans);
        }
    }
  • 相关阅读:
    windows下忘记mysql超级管理员root密码的解决办法
    windows防火墙支持FTP服务的设置方法
    IT人士不得不看的保健手册
    利用Google开发接口获取Google用户信息,OAuth2.0,profiles
    一个简单抓取糗事百科糗事的小程序
    JAVA 数据库编程
    JAVA 数据库编程(1)
    JAVA 数据库编程(2)
    css快速入门
    html5和css3新增特性
  • 原文地址:https://www.cnblogs.com/BriMon/p/9841522.html
Copyright © 2020-2023  润新知