AcWing 1285. 單詞
阿新 • • 發佈:2022-05-12
時間複雜度
時間複雜度是線性的,和所有單詞的總長度有關,也就是\(O(n)\)。
#include <bits/stdc++.h> using namespace std; const int N = 1000010; int n; int tr[N][26], idx; int f[N]; // 當前節點代表的字串在整個trie中出現的次數,也用來記錄遞推結果 char s[N]; // 字串 int id[210]; // 每個單詞在trie中對應節點的編號,比如id[1]=2,表示第一個模式串,在trie樹中是2號節點 void insert(int x) { int p = 0; for (int i = 0; s[i]; i++) { int t = s[i] - 'a'; if (!tr[p][t]) tr[p][t] = ++idx; p = tr[p][t]; f[p]++; //記錄p節點代表的字串在整個trie中出現的次數 } id[x] = p; //記錄x號單詞在trie樹中的節點編號 } int q[N], ne[N]; void build() { int hh = 0, tt = -1; for (int i = 0; i < 26; i++) if (tr[0][i]) q[++tt] = tr[0][i]; while (hh <= tt) { int t = q[hh++]; for (int i = 0; i < 26; i++) { if (!tr[t][i]) tr[t][i] = tr[ne[t]][i]; else { ne[tr[t][i]] = tr[ne[t]][i]; q[++tt] = tr[t][i]; } } } } int main() { scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%s", s); //構建Trie樹 insert(i); } //構建AC自動機 build(); //拓撲序更新 //從下向上遞推更新, trie中節點編號為0~idx,一共idx+1個點,0既代表根節點又代表空節點 for (int i = idx; i; i--) f[ne[q[i]]] += f[q[i]]; //輸出 for (int i = 0; i < n; i++) printf("%d\n", f[id[i]]); return 0; }