Trie图/AC自动机
下面是P3808 【模板】AC自动机(简单版) 的两种写法
Trie图
const int MAXN = 1000010;
int t[MAXN][26], word[MAXN], fail[MAXN], cnt, q[MAXN];
inline void insert(char *s) {
int u = 0;
for (int i = 1; s[i]; ++i) {
int v = s[i] - 'a';
int &x = t[u][v];
u = x ? x : x = ++cnt;
}
word[u]++;
}
inline void build() {
queue<int>q;
for (int i = 0; i < 26; ++i) if (t[0][i]) q.push(t[0][i]);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int i = 0; i < 26; ++i) {
int &x = t[u][i];
if (x) fail[x] = t[fail[u]][i], q.push(x);
else x = t[fail[u]][i];
}
}
}
inline int query(char *s) {
int u = 0, ans = 0;
for (int j = 1; s[j]; ++j) {
int v = s[j] - 'a';
u = t[u][v];
for (int i = u; i && word[i]; i = fail[i]) ans += word[i], word[i] = 0;
}
return ans;
}
int n; char s[1000007];
int main(void) {
in, n;
for (int i = 1; i <= n; ++i) {in, s + 1;insert(s);}
build();
in, s + 1;
int anss = query(s);
cout << anss;
return 0;
}
AC自动机
int t[N][26], word[N], fail[N], cnt, n, ans;
char s[N];
void insert(char *s) {
int u = 0;
for (int i = 1; s[i]; ++i) {
int &x = t[u][s[i] - 'a'];
u = x ? x : x = ++cnt;
}
++word[u];
}
void build() {
queue<int> q;
for (int i = 0; i < 26; ++i) if (t[0][i]) q.push(t[0][i]);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int i = 0; i < 26; ++i) {
int v = t[u][i], p = fail[u];
if (!v) continue;
while (p && !t[p][i]) p = fail[p];
fail[v] = t[p][i];
q.push(v);
}
}
}
void query(char *s) {
int u = 0, p = 0;
for (int i = 1; s[i]; ++i) {
u = t[u][s[i] - 'a'];
while (p && !t[p][s[i] - 'a']) p = fail[p];
p = t[p][s[i] - 'a'];
for (int k = p; k && word[k]; k = fail[k]) ans += word[k], word[k] = 0;
}
}
void init() {
}
void solve() {
n = in;
lo1(i, n) {
in, s + 1;
insert(s);
}
build();
in, s + 1;
query(s);
out, ans;
}