BZOJ3172 [Tjoi2013]单词 【AC自动机】
3172: [Tjoi2013]单词
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 4293 Solved: 2083
[Submit][Status][Discuss]
Description
某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。
Input
第一个一个整数N,表示有多少个单词,接下来N行每行一个单词。每个单词由小写字母组成,N<=200,单词长度不超过10^6
Output
输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。
Sample Input
3
a
aa
aaa
a
aa
aaa
Sample Output
6
3
1
3
1
复习了一下AC自动机
#include<iostream> #include<cstdio> #include<queue> #include<vector> #include<cstring> #include<algorithm> #define LL long long int #define REP(i,n) for (int i = 1; i <= (n); i++) using namespace std; const int maxn = 305,maxm = 1310005,INF = 1000000000; char T[maxm]; int pos[maxn],ans[maxn],ch[maxm][26],last[maxm],f[maxm],N,siz = 0;; vector<int> tag[maxm]; void insert(int p){ int u = 0,id; for (int j = pos[p - 1]; j < pos[p]; j++){ id = T[j] - 'a'; u = ch[u][id] ? ch[u][id] : ch[u][id] = ++siz; } tag[u].push_back(p); } void getf(){ queue<int> q; for (int i = 0; i < 26; i++) if (ch[0][i]) q.push(ch[0][i]); int u,v; while (!q.empty()){ u = q.front(); q.pop(); for (int i = 0; i < 26; i++){ v = ch[u][i]; if (!v) ch[u][i] = ch[f[u]][i]; else f[v] = ch[f[u]][i],q.push(v),last[v] = tag[f[v]].size() ? f[v]:last[f[v]]; } } } void re(int u){ while (u){ for (unsigned int j = 0; j < tag[u].size();j++) ans[tag[u][j]]++; u = last[u]; } } void AC(int p){ int u = 0,id; for (int i = pos[p - 1]; i < pos[p]; i++){ id = T[i] - 'a'; u = ch[u][id]; if (tag[u].size()) re(u); else if (last[u]) re(last[u]); } } int main() { scanf("%d",&N); for (int i = 1; i <= N; i++){ scanf("%s",T + pos[i - 1]); pos[i] = pos[i - 1] + strlen(T + pos[i - 1]); insert(i); } getf(); REP(i,N) AC(i); REP(i,N) printf("%d\n",ans[i]); return 0; }