Description
Randomly generate an article. If an article contains at least one word that users know, then we say the article is readable (we call article a contains word b, if and only if word b is a substring of article a).
Now give the N words that your users know, randomly generate articles of length M, and find out how many articles are readable.
Sample Input
2 2
A
B
Sample Output
100
This is a good question...
First of all, consider DP, and set f[i][j] as the number of readable articles matched to the position numbered j on the AC machine from the i-th bit.
For state f[i-1][j], consider what state it can update.
For the current i,j, enumerate 1-26 times, skip fail for each character, and skip to the inheritable position gg.
Then the DP equation is: f[i][gg]+=f[i-1][j].
#include <cstdio>
#include <cstring>
using namespace std;
int _max(int x, int y) {return x > y ? x : y;}
const int maxn = 110;
const int mod = 10007;
struct node {
int fail, v[30];
node() {memset(v, -1, sizeof(v));}
} t[maxn * 60]; int cnt, list[maxn * 60];
int cc[maxn * 60], f[maxn][60 * maxn];
char ss[maxn];
void bt() {
int x = 0;
int len = strlen(ss + 1);
for(int i = 1; i <= len; i++) {
int y = ss[i] - 'A' + 1;
if(t[x].v[y] == -1) t[x].v[y] = ++cnt;
x = t[x].v[y];
}
cc[x] = 1;
}
void get_fail() {
int head = 1, tail = 2;
list[1] = 0;
while(head != tail) {
int x = list[head];
for(int i = 1; i <= 26; i++) {
int y = t[x].v[i];
if(y == -1) continue;
if(x == 0) t[y].fail = 0;
else {
int j = t[x].fail;
while(j && t[j].v[i] == -1) j = t[j].fail;
t[y].fail = _max(0, t[j].v[i]);
}
list[tail++] = y;
}
if(cc[t[x].fail]) cc[x] = 1;
head++;
}
}
int main() {
int n, m; scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) {
scanf("%s", ss + 1);
bt();
}
get_fail();
f[0][0] = 1;
int kk = 1;
for(int i = 1; i <= m; i++) {
(kk *= 26) %= mod;
for(int j = 0; j <= cnt; j++) {
if(cc[j] || !f[i - 1][j]) continue;
for(int k = 1; k <= 26; k++) {
int u = j;
while(u && t[u].v[k] == -1) u = t[u].fail;
if(t[u].v[k] == -1) (f[i][0] += f[i - 1][j]) %= mod;
else (f[i][t[u].v[k]] += f[i - 1][j]) %= mod;
}
}
}
int ans = 0;
for(int i = 0; i <= cnt; i++) if(!cc[i]) (ans += f[m][i]) %= mod;
(ans = kk - ans) %= mod;
printf("%d\n", (ans + mod) % mod);
return 0;
}