inlinevoidinsert(char* s)// 字典树插入 { int u = 1, len = strlen (s); for (int i = 0; i < len; i ++) { v = s[i] - 'a'; if (!trie[u].son[v]) trie[u].son[v] = ++ cnt; // 记序号而并非字母,序号从 1 开始 u = trie[u].son[v]; } trie[u].flag ++; }
intquery(char* s) { int u = 1, ans = 0, len = strlen (s); for (int i = 0; i < len; i ++) { int v = s[i] - 'a', k = trie[u].son[v]; while (k > 1 && trie[k].flag != -1) { ans += trie[k].flag; // 计算有多少个模式串的贡献 trie[k].flag = -1; // 标记为走过 k = trie[k].fail; // 跳,跳,跳 } u = trie[u].son[v]; // 跳回去看另一种情况,一种是继续走,一种是在别的模式串上 } return ans; }
inlinevoidinsert(char* s) { int u = 1, len = strlen (s); for (int i = 0; i < len; i ++) { int v = s[i] - 'a'; if (!trie[u].son[v]) trie[u].son[v] = ++ cnt; u = trie[u].son[v]; } trie[u].flag ++; }
voidGetFail() { for (int i = 0; i < 26; i ++) trie[0].son[i] = 1; Q.push (1); trie[1].fail = 0; while (!Q.empty ()) { int u = Q.front (); Q.pop (); for (int i = 0; i < 26; i ++) { int v = trie[u].son[i], Fail = trie[u].fail; if (!v) trie[u].son[i] = trie[Fail].son[i]; else { trie[v].fail = trie[Fail].son[i]; Q.push (v); } } } }
intquery(char* s) { int u = 1, ans = 0, len = strlen (s); for (int i = 0; i < len; i ++) { int v = s[i] - 'a', k = trie[u].son[v]; while (k > 1 && trie[k].flag != -1) { ans += trie[k].flag; trie[k].flag = -1; k = trie[k].fail; } u = trie[u].son[v]; } return ans; }
intmain() { scanf ("%d", &n); for (int i = 1; i <= n; i ++) { scanf ("%s", s); insert (s); } GetFail (); scanf ("%s", s); printf ("%d", query (s)); return0; }
int n, cnt = 1, vis[N], ans; char s[151][N], q[N]; queue <int> Q;
inlinevoidinsert(char* s, int num) { int u = 1, len = strlen (s); for (int i = 0; i < len; i ++) { int v = s[i] - 'a'; if (!trie[u].son[v]) trie[u].son[v] = ++ cnt; u = trie[u].son[v]; } trie[u].flag = num; }
voidGetFail() { for (int i = 0; i < 26; i ++) trie[0].son[i] = 1; Q.push (1); trie[1].fail = 0; while (!Q.empty ()) { int u = Q.front (); Q.pop (); for (int i = 0; i < 26; i ++) { int v = trie[u].son[i], Fail = trie[u].fail; if (!v) trie[u].son[i] = trie[Fail].son[i]; else { trie[v].fail = trie[Fail].son[i]; Q.push (v); } } } }
intquery(char* s) { int u = 1, len = strlen (s); for (int i = 0; i < len; i ++) { int v = s[i] - 'a', k = trie[u].son[v]; while (k > 1) { if (trie[k].flag) vis[trie[k].flag] ++; k = trie[k].fail; } u = trie[u].son[v]; } return ans; }
inlinevoidclear() { for (int i = 1; i <= cnt; i ++) trie[i].clear (); for (int i = 1; i <= n; i ++) vis[i] = 0; cnt = 1, ans = 0; }
intmain() { while (1) { scanf ("%d", &n); if (!n) break; clear (); for (int i = 1; i <= n; i ++) { scanf ("%s", s[i]); insert (s[i], i); } scanf ("%s", &q); GetFail (); query (q); for (int i = 1; i <= n; i ++) ans = max (ans, vis[i]); printf ("%d\n", ans); for (int i = 1; i <= n; i ++) if (vis[i] == ans) printf ("%s\n", s[i]); } return0; }
voidquery(char *s)// 询问 { int u = 1, len = strlen (s); for (int i = 0; i < len; i ++) { u = trie[u].son[s[i] - 'a']; trie[u].ans ++; } }
拓扑
最后直接拓扑,没学的反正我也没写,天王老子都救不了你。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
voidTopulogy()// 拓扑 { for (int i = 1; i <= cnt; i ++) if (in[i] == 0) Q.push (i); while (!Q.empty ()) { int u = Q.front (); Q.pop (); vis[trie[u].flag] = trie[u].ans; // 如果有标记就更新答案 int v = trie[u].fail; in[v] --; trie[v].ans += trie[u].ans; // 更新 fail 的 ans if (in[v] == 0) Q.push (v); } }
char s[N], q[N]; int n, cnt = 1, vis[N], ans, in[N], mp[N];
structNode { int son[26], fail, flag, ans; } trie[N];
queue <int> Q;
inlinevoidinsert(char* s, int num) { int u = 1, len = strlen (s); for (int i = 0; i < len; i ++) { int v = s[i] - 'a'; if (!trie[u].son[v]) trie[u].son[v] = ++ cnt; u = trie[u].son[v]; } if (!trie[u].flag) trie[u].flag = num; mp[num] = trie[u].flag; }
voidGetFail() { for (int i = 0; i < 26; i ++) trie[0].son[i] = 1; Q.push (1); while (!Q.empty ()) { int u = Q.front (); Q.pop (); int Fail = trie[u].fail; for (int i = 0; i < 26; i ++) { int v = trie[u].son[i]; if (!v) trie[u].son[i] = trie[Fail].son[i]; else { trie[v].fail = trie[Fail].son[i]; in[trie[v].fail] ++; Q.push (v); } } } }
voidTopulogy() { for (int i = 1; i <= cnt; i ++) if (in[i] == 0) Q.push (i); while (!Q.empty ()) { int u = Q.front (); Q.pop (); vis[trie[u].flag] = trie[u].ans; int v = trie[u].fail; in[v] --; trie[v].ans += trie[u].ans; if (in[v] == 0) Q.push (v); } }
voidquery(char* s) { int u = 1, len = strlen (s); for (int i = 0; i < len; i ++) { u = trie[u].son[s[i] - 'a']; trie[u].ans ++; } }
intmain() { scanf ("%d", &n); for (int i = 1; i <= n; i ++) { scanf ("%s", s); insert (s, i); } GetFail (); scanf ("%s", q); query (q); Topulogy (); for (int i = 1; i <= n; i ++) printf ("%d\n", vis[mp[i]]); }
int head[M], edgecnt, id[N], tree[M], trie[M][26], cnt, root, top[M], hson[M], siz[M], dfsn[M], dfsx, fa[M], dep[M], n, temp[M], len, fail[M];
char st[M];
structEdge { int nxt, to; } edge[M];
inlinevoidadd_edge(int u, int v) { edge[++ edgecnt] = (Edge) {head[u], v}; head[u] = edgecnt; }
// Aho-Corasick Automation inlinevoidinsert(char st[M], int bh) { int u = 0, l = strlen (st + 1); for (int i = 1; i <= l; i ++) { int v = st[i] - 'a'; if (!trie[u][v]) trie[u][v] = ++ cnt; u = trie[u][v]; } id[bh] = u; }
voidGetFail() { queue <int> Q; for (int i = 0; i < 26; i ++) if (trie[root][i]) Q.push (trie[root][i]); while (!Q.empty ()) { int u = Q.front (); Q.pop (); for (int i = 0; i < 26; i ++) { if (trie[u][i]) { fail[trie[u][i]] = trie[fail[u]][i]; Q.push (trie[u][i]); } else trie[u][i] = trie[fail[u]][i]; } } }
// Heavy Path Decomposition
voidBuild_Fail_Tree() { for (int i = 1; i <= cnt; i ++) add_edge (fail[i], i); }
voiddfs1(int x) { dfsn[x] = ++ dfsx; siz[x] = 1; int maxn = 0; for (int i = head[x]; i; i = edge[i].nxt) { int v = edge[i].to; fa[v] = x; dep[v] = dep[x] + 1; dfs1 (v); siz[x] += siz[v]; if (siz[v] > maxn) { maxn = siz[v]; hson[x] = v; } } return; }
voiddfs2(int x, int topf) { top[x] = topf; if (!hson[x]) return ; dfs2 (hson[x], topf); for (int i = head[x]; i; i = edge[i].nxt) { int v = edge[i].to; if (v == hson[x]) continue; dfs2 (v, v); } }
intcmp(int a, int b) { return dfsn[a] < dfsn[b]; }
// Lowest Common Ancestors
inlineintlca(int x, int y) { while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap (x, y); x = fa[top[x]]; } return dep[x] < dep[y] ? x : y; }
// Binary Index Tree
inlineintlowbit(int x) { return x & -x; }
inlinevoidadd(int pos, int val) { for (int i = pos; i <= cnt + 1; i += lowbit (i)) tree[i] += val; }
inlineintquery(int pos) { int res = 0; for (int i = pos; i; i -= lowbit (i)) res += tree[i]; return res; }
// Main function
intmain() { scanf ("%d", &n); for (int i = 1; i <= n; i ++) { scanf ("%s", st + 1); insert (st, i); } GetFail (); Build_Fail_Tree (); dep[0] = 1; dfs1 (0); dfs2 (0, 0); int m, op; scanf ("%d", &m); while (m --) { scanf ("%d", &op); if (op == 1) { scanf ("%s", st + 1); len = 0; int u = 0, l = strlen (st + 1); for (int i = 1; i <= l; i ++) { int v = st[i] - 'a'; u = trie[u][v]; temp[++ len] = u; } sort (temp + 1, temp + len + 1, cmp); len = unique (temp + 1, temp + len + 1) - temp - 1; for (int i = 1; i <= len; i ++) { add (dfsn[temp[i]], 1); if (i > 1) add (dfsn[lca (temp[i], temp[i - 1])], -1); } } else { scanf ("%d", &op); printf ("%d\n", query (dfsn[id[op]] + siz[id[op]] - 1) - query (dfsn[id[op]] - 1)); } } return0; }