10 2 2 hello world 4 1 1 icpc 10 0 0 0 0 0
2 114195065
ac自动机+状压dp
#include<stdio.h> #include<string.h> #include<queue> #include<malloc.h> using namespace std; const int maxn = 1000005; const int base = 20090717; int n, m, K, f[2][105][1024]; class tire { public: tire *down[26], *next; int end, cnt; tire(){ next = NULL; cnt = end = 0; memset(down, 0, sizeof(down)); } void assign(){ next = NULL; end = 0; memset(down, 0, sizeof(down)); } }; class ac_automaton { private: tire *root; tire *node[105]; int tot; char s[maxn]; char S[maxn]; int mask[2048]; public: ac_automaton(){ node[0] = root = new tire; tot = 0; memset(mask, 0, sizeof(mask)); for (int i = 0; i < 1024; i++) mask[i] = mask[i >> 1] + (i & 1); } void clear(){ node[0] = root = new tire; tot = 0; } void insert(int x) { scanf("%s", s); tire* j = root; for (int i = 0, k; s[i]; i++) { k = s[i] - 'a'; if (!j->down[k]) { node[++tot] = j->down[k] = new tire; node[tot]->cnt = tot; } j = j->down[k]; } j->end = 1 << (x - 1); } void getnext() { queue<tire*> p; tire *q, *k, *j; root->next = root; for (int i = 0; i < 26; i++) if (root->down[i]) { q = root->down[i]; q->next = root; p.push(q); } else root->down[i] = root; while (!p.empty()) { q = p.front(); p.pop(); k = q->next; for (int i = 0; i < 26; i++) if (q->down[i]) { j = q->down[i]; j->next = k->down[i]; j->end |= k->down[i]->end; p.push(q->down[i]); } else q->down[i] = k->down[i]; } } int getmother() { scanf("%s", S); root = new tire; return strlen(S); } int work_out() { getnext(); memset(f[0], 0, sizeof(f[0])); f[0][0][0] = 1; int M = (1 << m), u = 0; tire *a, *b; for (int i = 0; i < n; i++) { u = (u + 1) & 1; for (int j = 0; j <= tot; j++) for (int k = 0; k < M; k++) f[u][j][k] = 0; for (int j = 0; j <= tot; j++) for (int k = 0; k < M; k++) if (f[u ^ 1][j][k]) { a = node[j]; for (int v = 0; v < 26; v++) { b = a->down[v]; (f[u][b->cnt][b->end | k] += f[u ^ 1][j][k]) %= base; } } } int ans = 0; for (int i = 0; i <= tot; i++) for (int j = 0; j < M; j++) if (mask[j] >= K) ans = (ans + f[u][i][j]) % base; return ans; } }F; int main() { while (scanf("%d%d%d", &n, &m, &K), n + m + K) { F.clear(); for (int i = 0; i < m; i++) F.insert(i + 1); printf("%d\n", F.work_out()); } return 0; }