洛谷 P6257 / LOJ 6583 / CodeForces Gym 102511G 「ICPC World Finals 2019」First of Her Name

洛谷传送门

LOJ 传送门

CF Gym 传送门

思路

先建出来原来 \(n\) 个串的 Trie,再对询问串的反串建 AC 自动机,则一个串 \(S\) 在 AC 自动机上的所有后缀就是不断跳 \(\mathrm{fail}\) 直到根结点。建出 \(\mathrm{fail}\) 树后统计子树和即可。

代码

code
/*

p_b_p_b txdy
AThousandMoon txdy
AThousandSuns txdy
hxy txdy

*/

#include <bits/stdc++.h>
#define pb push_back
#define fst first
#define scd second

using namespace std;
typedef long long ll;
typedef pair<ll, ll> pii;

const int maxn = 1000100;

int ch[maxn][26], tot, n, m, head[maxn], len;
char s[maxn];

struct edge {
	int to, next;
} edges[maxn << 1];

void add_edge(int u, int v) {
	edges[++len].to = v;
	edges[len].next = head[u];
	head[u] = len;
}

struct AC {
	int ch[maxn][26], tot, sz[maxn], idx[maxn], fail[maxn];
	
	void insert(char *s, int id) {
		int p = 0;
		for (int i = 0; s[i]; ++i) {
			if (!ch[p][s[i] - 'A']) {
				ch[p][s[i] - 'A'] = ++tot;
			}
			p = ch[p][s[i] - 'A'];
		}
		idx[id] = p;
	}
	
	void build() {
		queue<int> q;
		for (int i = 0; i < 26; ++i) {
			if (ch[0][i]) {
				q.push(ch[0][i]);
			}
		}
		while (q.size()) {
			int u = q.front();
			q.pop();
			for (int i = 0; i < 26; ++i) {
				if (ch[u][i]) {
					fail[ch[u][i]] = ch[fail[u]][i];
					q.push(ch[u][i]);
				} else {
					ch[u][i] = ch[fail[u]][i];
				}
			}
		}
		for (int i = 1; i <= tot; ++i) {
			add_edge(fail[i], i);
		}
	}
	
	void dfs(int u) {
		for (int i = head[u]; i; i = edges[i].next) {
			int v = edges[i].to;
			dfs(v);
			sz[u] += sz[v];
		}
	}
} ac;

void dfs(int u, int k) {
	++ac.sz[k];
	for (int i = 0; i < 26; ++i) {
		if (ch[u][i]) {
			dfs(ch[u][i], ac.ch[k][i]);
		}
	}
}

void solve() {
	scanf("%d%d", &n, &m);
	for (int i = 1, p; i <= n; ++i) {
		scanf("%s%d", s, &p);
		ch[p][s[0] - 'A'] = ++tot;
	}
	for (int i = 1; i <= m; ++i) {
		scanf("%s", s);
		int len = strlen(s);
		reverse(s, s + len);
		ac.insert(s, i);
	}
	ac.build();
	dfs(0, 0);
	ac.dfs(0);
	for (int i = 1; i <= m; ++i) {
		printf("%d\n", ac.sz[ac.idx[i]]);
	}
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}
posted @ 2022-06-26 13:31  zltzlt  阅读(29)  评论(0编辑  收藏  举报