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;
}