zoukankan      html  css  js  c++  java
  • HDU 2825 Wireless Password

    Wireless Password

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

    题意:

      求有多少长度为n的串,包含给定的串的至少k个串。

    分析:

      AC自动机+dp,首先对给定的m个串建立AC自动机,然后状压dp,dp[i][j][s]表示当前的串的长度是i,在AC自动机的节点j上,状态(已经满足的串)是s的方案数。

      注意:1、将每个点所满足的所有串,都或起来,这个点可以把这些子串都包含进去。2、代码40行要有,在AC自动机上一旦不匹配了,就可以走回去了。

    代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<cmath>
     6 #include<cctype>
     7 #include<set>
     8 #include<queue>
     9 #include<vector>
    10 #include<map>
    11 using namespace std;
    12 typedef long long LL;
    13 
    14 inline int read() {
    15     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    16     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    17 }
    18 
    19 const int mod = 20090717;
    20 
    21 int dp[26][150][1200], ch[150][27], sta[150], q[150], fail[150], Index;
    22 char s[150];
    23 
    24 void Insert(char *s,int id) {
    25     int n = strlen(s), u = 0;
    26     for (int i = 0; i < n; ++i) {
    27         int c = s[i] - 'a';
    28         if (!ch[u][c]) ch[u][c] = ++Index;
    29         u = ch[u][c];
    30     }
    31     sta[u] |= (1 << id);
    32 }
    33 void bfs() {
    34     int L = 1, R = 0;
    35     for (int i = 0; i < 26; ++i) if (ch[0][i]) q[++R] = ch[0][i]; // q[++R] = i!!!
    36     while (L <= R) {
    37         int u = q[L ++];
    38         for (int c = 0; c < 26; ++c) {
    39             int v = ch[u][c];
    40             if (!v) { ch[u][c] = ch[fail[u]][c]; continue; }
    41             int p = fail[u]; while (p && !ch[p][c]) p = fail[p];
    42             fail[v] = ch[p][c];
    43             q[++R] = v;
    44             sta[v] |= sta[fail[v]]; 
    45         }
    46     }
    47 }
    48 inline void add(int &x,int y) { x += y; if (x >= mod) x -= mod; }
    49 inline void sub(int &x,int y) { x -= y; x < 0 && (x += mod); } 
    50 void solve(int n,int m,int k) {
    51     dp[0][0][0] = 1;
    52     int All = (1 << m) - 1;
    53     for (int i = 0; i < n; ++i) 
    54         for (int j = 0; j <= Index; ++j) 
    55             for (int s = 0; s <= All; ++s) {
    56                 if (dp[i][j][s] <= 0) continue; 
    57                 for (int c = 0; c < 26; ++c) {
    58                     int nv = ch[j][c], ns = s | sta[nv];
    59                     add(dp[i + 1][nv][ns], dp[i][j][s]);
    60                 }
    61             }
    62     int ans = 0;
    63     for (int s = 0; s <= All; ++s) {
    64         int cnt = 0;
    65         for (int i = 0; i < m; ++i) if ((s >> i) & 1) cnt ++;
    66         if (cnt >= k) {
    67             for (int i = 0; i <= Index; ++i) add(ans, dp[n][i][s]);
    68         }
    69     }
    70     printf("%d
    ",ans);
    71 }
    72 void init() {
    73     Index = 0;
    74     memset(ch, 0, sizeof(ch));
    75     memset(sta, 0, sizeof(sta));
    76     memset(dp, 0, sizeof(dp));
    77     memset(fail, 0, sizeof(fail));
    78 }
    79 int main() {
    80     int n, m, k;
    81     while (~scanf("%d%d%d", &n, &m, &k)) {
    82         if (!n && !m && !k) break;
    83         init();
    84         for (int i = 1; i <= m; ++i) {
    85             scanf("%s", s); Insert(s, i - 1);
    86         }
    87         bfs();
    88         solve(n, m, k);        
    89     }
    90     return 0;
    91 }
  • 相关阅读:
    oracle归档空间不足的问题(rman删除归档日志)
    oracle DG查看延时时间
    Convert JS object to JSON string
    转:微信公众平台开发(80) 上传下载多媒体文件
    生成带参数的二维码
    关闭微信浏览器可以使用
    微信内置浏览器的JsAPI(WeixinJSBridge续)进入全屏
    如何隐藏微信公众平台右上角按钮
    微信公众平台服务号、订阅号的相关说明选择字号:
    微信公众平台群发消息的方法及注意事项
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10090288.html
Copyright © 2011-2022 走看看