Cansult's blog

即使愿望永远无法实现
我也不愿就这样放手

0%

翻车笔记 [JSOI2007]文本生成器 [AC自动机, 翻车, 清奇脑回路]

又忘了计数题算补集这回事了

感觉trie的好处就是一个节点代表一个串啊?

又及: wdnmd真都一个错误犯三次啊

懵逼的 题目

BZOJ

扯淡的 题解

一开始想着是在trie上遍历然后算贡献云云 然后发现这个容斥似乎有点反人类

然后抄题解第一句就是取补集

Emmmmm...

f[i][j]代表当前生成第i位, 匹配到了自动机的第j个点上 没有出现过已知单词的方案数

然后随便写写就好了

沙茶的 代码

我构建fail的时候又㕛叒叕忘了把下一层push进去了

这是有多大仇...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/**************************************************************
Problem: 1030
User: Cansult
Language: C++
Result: Accepted
Time:184 ms
Memory:4460 kb
****************************************************************/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#define MAXN (6000 + 5)
#define MAXM (100 + 5)
#define MAXC (26)
#define Aufun (10007)
using namespace std;
struct node {
int son[MAXC], fail;
vector<int> bh;
} b[MAXN];
int n, m, f[MAXM][MAXN], cntb, ans;
char s[MAXM];
void init() {
queue<int> q;
for (int i = 0; i < MAXC; i++) if (b[0].son[i]) q.push(b[0].son[i]);
while (!q.empty()) {
int dq = q.front();
q.pop();
for (int i = 0; i < MAXC; i++)
if (b[dq].son[i]) b[b[dq].son[i]].fail = b[b[dq].fail].son[i], q.push(b[dq].son[i]);
else b[dq].son[i] = b[b[dq].fail].son[i];
}
}
int mpow(int a, int b) {
int re = 1;
for (int i = 1; i <= b; i++)
re *= a, re %= Aufun;
return re;
}
bool pd(int dq) {
for (int i = dq; i; i = b[i].fail)
if (b[i].bh.size())
return false;
return true;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%s", s);
int dqn = strlen(s), dq = 0;
for (int j = 0; j < dqn; j++) {
if (!b[dq].son[s[j] - 'A']) b[dq].son[s[j] - 'A'] = ++cntb;
dq = b[dq].son[s[j] - 'A'];
}
b[dq].bh.push_back(i);
}
init();
f[0][0] = 1;
for (int i = 0; i < m; i++)
for (int j = 0; j <= cntb; j++)
if (f[i][j])
for (int k = 0; k < MAXC; k++)
if (pd(b[j].son[k]))
f[i + 1][b[j].son[k]] += f[i][j], f[i + 1][b[j].son[k]] %= Aufun;
for (int i = 0; i <= cntb; i++) ans += f[m][i], ans %= Aufun;
printf("%d", ((mpow(26, m) - ans) % Aufun + Aufun) % Aufun);
return 0;
}

By 准备退役旅游的 Cansult