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

进度这么慢,省选爆零节奏(=゚ω゚)ノ

posted @ 2016-04-05 20:42  abclzr  阅读(210)  评论(0编辑  收藏  举报