P3966 [TJOI2013]单词
Posted zgglj-com
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3966 [TJOI2013]单词相关的知识,希望对你有一定的参考价值。
题意:给n个单词,问每个单词在n个单词中出现了几次? a 在 acdnsaana 中出现了4次。
ps:AC自动机的模板题,就注意一点:一定要从这棵树的底部向上遍历累加贡献。
const int N = 1000010; struct node { int fail, Count; int vis[26]; node() { mem(vis, 0); fail = Count = 0; } }; struct AcToMation { node a[N]; int tot, sum[N], id[300]; stack<int> st; void Inite() { tot = 0; mem(sum, 0); } void Build(char *s, int t) { int n = strlen(s); int now = 0; rep(i, 0, n) { if (!a[now].vis[s[i] - ‘a‘]) a[now].vis[s[i] - ‘a‘] = ++tot; now = a[now].vis[s[i] - ‘a‘]; sum[now]++; } a[now].Count++; id[t] = now; } void getFail() { queue<int> q; rep(i, 0, 26) if (a[0].vis[i]) { a[a[0].vis[i]].fail = 0; q.push(a[0].vis[i]); } while(!q.empty()) { int now = q.front(); q.pop(); st.push(now); rep(i, 0, 26) { if (a[now].vis[i]) { a[a[now].vis[i]].fail = a[a[now].fail].vis[i]; q.push(a[now].vis[i]); } else { a[now].vis[i] = a[a[now].fail].vis[i]; } } } } void Compute(int n) { while(!st.empty()) { sum[a[st.top()].fail] += sum[st.top()]; st.pop(); } Rep(i, 1, n) pr(sum[id[i]]); } }; AcToMation ac; int main() { ac.Inite(); int n; char s[N]; sc(n); Rep(i, 1, n) { scanf("%s", s); ac.Build(s, i); } ac.getFail(); ac.Compute(n); return 0; }
以上是关于P3966 [TJOI2013]单词的主要内容,如果未能解决你的问题,请参考以下文章
P3966 [TJOI2013]单词(AC自动机,fail树)