[TJOI 2013]单词

时间:2023-03-10 02:42:44
[TJOI 2013]单词

Description

题库链接

给出一篇文章的所有单词,询问每个单词出现的次数。

单词总长 \(\leq 10^6\)

Solution

算是 \(AC\) 自动机的板子,注意拼成文章的时候要在单词间加上个不会出现的字符。同时注意匹配时会访问这个字符,所以在 \(trie\) 树上要多开一维。

我的代码慢的飞起...看提交基本都几百 \(ms\) ,我在超时边缘...

Code

//It is made by Awson on 2018.2.5
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n'))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int N = 1e6+200;
void read(int &x) {
char ch; bool flag = 0;
for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
x *= 1-2*flag;
}
void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); } queue<int>Q;
int n, cnt[205], loc = -1, mp[205];
char T[N+5], S[N+5];
struct AC_Automaton {
int ch[N+5][27], val[N+5], f[N+5], pos;
void insert(int id) {
int len = strlen(T), u = 0;
for (int i = 0; i < len; i++) {
if (ch[u][T[i]-'a'] == 0) ch[u][T[i]-'a'] = ++pos;
u = ch[u][T[i]-'a'];
}
if (val[u] == 0) mp[id] = val[u] = id;
else mp[id] = val[u];
}
void build() {
while (!Q.empty()) Q.pop();
for (int i = 0; i < 27; i++) if (ch[0][i]) f[ch[0][i]] = 0, Q.push(ch[0][i]);
while (!Q.empty()) {
int u = Q.front(); Q.pop();
for (int i = 0; i < 27; i++)
if (ch[u][i]) f[ch[u][i]] = ch[f[u]][i], Q.push(ch[u][i]);
else ch[u][i] = ch[f[u]][i];
}
}
void query() {
int len = strlen(S), u = 0;
for (int i = 0; i < len; i++) {
u = ch[u][S[i]-'a'];
for (int j = u; j; j = f[j]) if (val[j]) ++cnt[val[j]];
}
}
}AC; void add() {
int len = strlen(T); S[++loc] = 'a'+26;
for (int i = 0; i < len; i++) S[++loc] = T[i];
}
void work() {
read(n);
for (int i = 1; i <= n; i++) {
scanf("%s", T); AC.insert(i); add();
}
AC.build(); AC.query();
for (int i = 1; i <= n; i++) writeln(cnt[mp[i]]);
}
int main() {
work(); return 0;
}