P4595 [COCI2011-2012#5] POPLOCAVANJE

P4595 [COCI2011-2012#5] POPLOCAVANJE
第一反应AC自动机,好家伙,竟然只有 62.5MB 空间。那么我直接放弃没想法。那咱们先不考虑时间。
第一重优化时间:发现要匹配也就匹配最长的串,所以在fail树上记一下fail能跳到的最长串。
发现每个串的询问其实互相独立,所以考虑可以分块建AC自动机,然后直接分块做完了。

/*
	Name:
	Author: Gensokyo_Alice
	Date:
	Description:
*/
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <map>
#include <set>

using namespace std;

typedef int ll;
const ll MAXN = 1e6+10;

ll N, M, tot, tag[MAXN], tim, vis[MAXN], head[MAXN], cnt = -1, maxn[MAXN], ans[MAXN], sum;
char ss[MAXN], st[MAXN];

struct nod {
	ll fail, cnt, nt[26];
} t[MAXN];

struct edge {
	ll nt, to;
} E[MAXN];

void ins(char*, ll);
void bfs();
void cha();
void add(ll, ll);
void dfs(ll); 
void clear(ll);

int main() {
	memset(head, -1, sizeof(head)); 
	scanf("%d", &N);
	scanf("%s", ss+1);
	scanf("%d", &M);
	ll SIZ = sqrt(M);
	for (ll i = 1; i <= M; i += SIZ) {
		tot = 0;
		for (ll j = i; j < i + SIZ && j <= M; j++) {
			scanf("%s", st+1);
			ins(st, strlen(st+1));
		}
		bfs();cha(); tim++;
		clear(0); tag[0] = tim;
	}
	for (ll i = 1; i <= N; i++) ans[i] += ans[i-1], sum += (ans[i] == 0);
	printf("%d
", sum);
    return 0;
}

void cha() {
	ll now = 0;
	for (ll i = 1; i <= N; i++) {
		now = t[now].nt[ss[i]-'a'];
		ans[i+1] -= 1, ans[i-maxn[now]+1] += 1;
	}
}

void ins(char* tem, ll len) {
	ll now = 0;
	for (ll i = 1; i <= len; i++) {
		if (!t[now].nt[tem[i]-'a']) t[now].nt[tem[i]-'a'] = ++tot, clear(tot); 
		now = t[now].nt[tem[i]-'a'];
	}
	t[now].cnt = len;
}

void clear(ll now) {if (tag[now] < tim) tag[now] = tim, maxn[now] = 0, t[now].cnt = 0, t[now].fail = 0, memset(t[now].nt, 0, sizeof(t[now].nt)); }

void bfs() {
	queue <ll> q;
	q.push(0);
	while (!q.empty()) {
		ll nt = q.front(); q.pop();
		for (ll i = 0; i < 26; i++) {
			ll son = t[nt].nt[i];
			if (son) {q.push(son); if (!nt) continue; t[son].fail = t[t[nt].fail].nt[i];}
			else t[nt].nt[i] = t[t[nt].fail].nt[i];
		}
	}
	for (ll i = 0; i <= tot; i++) head[i] = -1; cnt = -1;
	for (ll i = 1; i <= tot; i++) add(t[i].fail, i);
	dfs(0);
}

void dfs(ll n) {
	maxn[n] = max(maxn[n], t[n].cnt);
	for (ll i = head[n]; ~i; i = E[i].nt) {
		ll v = E[i].to;
		maxn[v] = maxn[n];
		dfs(v);
	}
}

void add(ll x, ll y) {
	cnt++;
	E[cnt].to = y;
	E[cnt].nt = head[x];
	head[x] = cnt;
}
原文地址:https://www.cnblogs.com/Gensokyo-Alice/p/14023736.html