【BZOJ 2434】【NOI 2011】阿狸的打字机 fail树
完全不会啊,看题解还看了好久,我是蒟蒻$QAQ$
$zyf$的题解挺好的:http://blog.csdn.net/clove_unique/article/details/51059425
$fail树$的性质完全不知道啊,只好现学,,,
根据读入的顺序来扫$Trie树$并更新树状数组真的好神!我一辈子都想不出来$TwT$
还有$dfs序$那里我还想了好久,,,聪哥说我的表情一脸懵逼
最终看(抄)题解做出来了,用了$4h+$,我好制杖
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> #define N 200003 #define lowbit(x) (x & (-x)) #define read(x) x=getint() using namespace std; inline int getint() { int k = 0, fh = 1; char c = getchar(); for(; c < '0' || c > '9'; c = getchar()) if (c == '-') fh = -1; for(; c >= '0' && c <= '9'; c = getchar()) k = k * 10 + c - '0'; return k * fh; } struct node { int nxt, to; } E[N * 26]; int fa[N], watch[N], c[N][26], cnt = 0, tot = 0, point[N]; int fail[N], L[N], R[N], C[N], m, ans[N]; inline void _(char *s) { int len = strlen(s), now = 0; for(int i = 0; i < len; ++i){ if (s[i] >= 'a' && s[i] <= 'z') { int t = s[i] - 'a'; if (!c[now][t]) c[now][t] = ++cnt; fa[cnt] = now; now = cnt; }else if (s[i] == 'P') watch[++tot] = now; else now = fa[now]; } } inline void ins(int x, int y) {E[++cnt].nxt = point[x]; E[cnt].to = y; point[x] = cnt;} inline void __() { cnt = 0; queue <int> q; for(int t = 0; t < 26; ++t) if (c[0][t]) q.push(c[0][t]), ins(0, c[0][t]); while (!q.empty()) { int now = q.front(); q.pop(); for(int t = 0; t < 26; ++t) if (!c[now][t]) c[now][t] = c[fail[now]][t]; else { int u = c[now][t]; fail[u] = c[fail[now]][t]; ins(fail[u], u); q.push(u); } } } inline void ___(int x) { L[x] = ++cnt; for(int tmp = point[x]; tmp; tmp = E[tmp].nxt) ___(E[tmp].to); R[x] = cnt; } inline void inc(int pos, int num) { for(; pos <= cnt; pos += lowbit(pos)) C[pos] += num; } inline int sum(int pos) { int s = 0; for(; pos > 0; pos -= lowbit(pos)) s += C[pos]; return s; } struct nnode { int x, y, id; } A[N]; inline bool cmp(nnode n1, nnode n2) {return n1.y < n2.y;} int main() { char s[N << 1]; scanf("%s", s); _(s); __(); cnt = 0; ___(0); read(m); for(int i = 1; i <= m; ++i) read(A[i].x), read(A[i].y), A[i].id = i; sort(A + 1, A + m + 1, cmp); int len = strlen(s), now = 0, con =1; tot = 0; for(int i = 0; i < len; ++i) { if (s[i] >= 'a' && s[i] <= 'z') now = c[now][s[i] - 'a'], inc(L[now], 1); else if (s[i] == 'P') { if (++tot == A[con].y) { for(; tot == A[con].y; ++con) ans[A[con].id] = sum(R[watch[A[con].x]]) - sum(L[watch[A[con].x]] - 1); } } else inc(L[now], -1), now = fa[now]; } for(int i = 1; i <= m; ++i) printf("%d\n", ans[i]); return 0; }
进度这么慢,省选爆零节奏(=゚ω゚)ノ
NOI 2017 Bless All