zoukankan      html  css  js  c++  java
  • HDU 2825 Wireless Password AC自动机 + DP

    HDU 2825
      1 /*
    2 * hdu 2825 Wireless Password
    3 * —— 2011-11-10/15:41 开始敲
    4 * —— 2011-11-10/16:27 结束敲
    5 * —— 2011-11-10/20:10 靠柯神Debug成功
    6 *
    7 * 题意:
    8 * 给定1个有m(m<=10)个字符串(长度<=10)的集合,
    9 * 从其中取不少于k个串(k<=m),拼成一个长为n的串,
    10 * 这个串可以互相重叠,问有多少种组合。(答案%20090717)
    11 *
    12 * 思路:
    13 * dp[i][j][k]:当前长为i的串走到Trie图上的j号节点,
    14 * 已取k状态(位表示取了哪些串)时,最多能有多少方案
    15 * 转移方程:dp[i+1][child[j].id][k|child[j].tag] += dp[i][j][k]
    16 *
    17 * 复杂度:O(n * m * 2^m * 字符集大小) 其中2^m用来状态压缩
    18 *
    19 * 错误:
    20 * 1. inti_root()中没有对root和tot进行初始化 = =
    21 * 2. 才发现原来的一个重大错误,我在进行DP的时候,
    22 * 其实没有DP到底,循环第二维的时候少了一个等号,
    23 * Trie图上的最后一个节点没走到,做POJ-3691却过了,
    24 * POJ的数据果然不够强大
    25 */
    26
    27 #include <stdio.h>
    28 #include <iostream>
    29 #include <string.h>
    30 #include <math.h>
    31 using namespace std;
    32
    33 #define N 105
    34 #define cls(a, b) memset(a, b, sizeof(a))
    35 #define begin 'a'
    36 #define kind 26
    37 #define MOD 20090717
    38
    39 int root, tot;
    40 int que[N], head, tail;
    41 int f[30][N][1030];
    42 int map[1030];
    43
    44 struct node{
    45 int ch[kind], tag, fail;
    46 void init(){ cls(ch, 0); tag = 0; fail = -1; }
    47 }T[N];
    48
    49 void init_root()
    50 {
    51 root = tot = 0;
    52 T[root].init();
    53 }
    54 void insert(char *s, int id)
    55 {
    56 int p = root, idx;
    57 while(*s)
    58 {
    59 idx = *(s++) - begin;
    60 if(!T[p].ch[idx])
    61 {
    62 T[++tot].init();
    63 T[p].ch[idx] = tot;
    64 }
    65 p = T[p].ch[idx];
    66 }
    67 T[p].tag |= (1<<id);
    68 }
    69 void build_AC()
    70 {
    71 head = tail = 0;
    72 que[tail++] = root;
    73 while(head < tail)
    74 {
    75 int u = que[head++];
    76 for(int i=0; i<kind; i++)
    77 {
    78 if(T[u].ch[i])
    79 {
    80 int son = T[u].ch[i];
    81 int p = T[u].fail;
    82 if(u == root)
    83 T[son].fail = root;
    84 else{
    85 T[son].fail = T[p].ch[i];
    86 T[son].tag |= T[T[p].ch[i]].tag; //传递标记
    87 }
    88 que[tail++] = son;
    89 }else{
    90 if(u == root) T[u].ch[i] = root;
    91 else T[u].ch[i] = T[T[u].fail].ch[i];
    92 }
    93 }
    94 }
    95 }
    96 void init_map()
    97 {
    98 int d = 1<<10;
    99 map[0] = 0;
    100 for(int i=1; i<d; i++)
    101 map[i] = map[i>>1] + (i&1);
    102 }
    103 void solve()
    104 {
    105 int n, m, d, i, j, k, t, mx, son, tag;
    106 char str[50];
    107 init_map();
    108 while(~scanf("%d%d%d", &n, &m, &t) && (n||m||t))
    109 {
    110 init_root();
    111 for(i=0; i<m; i++)
    112 {
    113 scanf("%s", str);
    114 insert(str, i);
    115 }
    116 build_AC();
    117 mx = 1 << m;
    118 cls(f, 0);
    119 f[0][0][0] = 1;
    120 for(i=0; i<n; i++)
    121 for(j=0; j<=tot; j++) //因为这个等号的问题内伤了
    122 for(k=0; k<mx; k++)
    123 {
    124 if(!f[i][j][k]) continue;
    125 for(d=0; d<kind; d++)
    126 {
    127 son = T[j].ch[d];
    128 tag = T[son].tag;
    129 f[i+1][son][k|tag] += f[i][j][k];
    130 if(f[i+1][son][k|tag] >= MOD)
    131 f[i+1][son][k|tag] %= MOD;
    132 }
    133 }
    134 int sum = 0;
    135 for(i=0; i<=tot; i++)
    136 for(j=0; j<mx; j++)
    137 {
    138 if(map[j]>=t) {
    139 sum+=f[n][i][j];
    140 if(sum >= MOD) sum %= MOD;
    141 }
    142 }
    143 printf("%d\n", sum);
    144 }
    145 }
    146
    147 int main()
    148 {
    149 #ifdef Nstd
    150 freopen("E:\\workspace\\in.txt", "r+", stdin);
    151 #endif
    152 solve();
    153 return 0;
    154 }

    题外话,昨晚弄到1点多才回去的,一路上和P神、柯神聊到寝室楼下。大门紧闭,沙茶的我们以为门锁了,去按了一下门铃,按完才发现其实没锁。。

    赶紧一溜烟地跑回了楼上,留下大叔独自在门卫室黯然神伤。。 大叔对不住了!!!

  • 相关阅读:
    杭电2054
    M1/M2总结
    软件开发相关的读书笔记 问题与方法
    代码复审1234跟我一起来
    电梯调度算法简述
    Pair_Work Project
    读书笔记摘录:
    Individual Project
    个人阅读作业——软件工程M1/M2的总结
    个人阅读作业2
  • 原文地址:https://www.cnblogs.com/Nstd/p/2244923.html
Copyright © 2011-2022 走看看