【BZOJ 2555】SubString

http://www.lydsy.com/JudgeOnline/problem.php?id=2555
一个字符串在原串中的出现次数就是这个字符串对应后缀自动机上的状态的\(|Right|\),要求parent树中这个状态的子树中叶子节点的个数。
因为强制在线,所以用lct维护parent树以及树上每个节点的\(|Right|\)
注意新建\(nq\)节点时nq节点的值要设为0,因为\(nq\)节点不是叶子节点。。。
还有删整棵子树时要减去它们对它们祖先的影响。
lct模板打错,调了好长时间_(:з」∠)_
压常数?inline大法好

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

struct node *null;
struct node {
	node *ch[2], *fa;
	int r, lazy;
	node() {
		ch[0] = ch[1] = fa = null;
		r = lazy = 0;
	}
	bool pl() {return fa->ch[1] == this;}
	bool check() {return fa == null || (fa->ch[0] != this && fa->ch[1] != this);}
	void setc(node *r, bool c) {ch[c] = r; r->fa = this;}
	void push() {
		if (lazy != 0) {
			if (ch[0] != null) ch[0]->lazy += lazy, ch[0]->r += lazy;
			if (ch[1] != null) ch[1]->lazy += lazy, ch[1]->r += lazy;
			lazy = 0;
		}
	}
};

namespace LCT {
	inline void rotate(node *r) {
		node *f = r->fa;
		bool c = r->pl();
		if (f->check()) r->fa = f->fa;
		else f->fa->setc(r, f->pl());
		f->setc(r->ch[!c], c);
		r->setc(f, !c);
	}
	inline void update(node *r) {
		if (!r->check())
		update(r->fa);
		r->push();
	}
	inline void splay(node *r) {
		update(r);
		for(; !r->check(); rotate(r))
			if (!r->fa->check()) rotate(r->pl() == r->fa->pl() ? r->fa : r);
	}
	inline void access(node *r) {
		node *y = null;
		while (r != null) {
			splay(r);
			r->ch[1] = y;
			y = r;
			r = r->fa;
		}
	}
	inline void cut_to(node *r, node *f) {
		access(r); splay(r);
		int tot = r->r;
		node *t = r->ch[0]; t->fa = null;
		t->r -= tot; t->lazy -= tot;
		
		r->ch[0] = null;
		r->fa = f;
		access(f); splay(f);
		f->r += tot; f->lazy += tot;
	}
	inline void link_to(node *r, node *f) {
		r->fa = f;
		access(r); splay(r);
		r->r = r->lazy = 1;
	}
	inline void link_to_nq(node *r, node *f) {
		r->fa = f;
	}
}

struct State {
	State *par, *go[26];
	int val;
	node *to;
	State(int _val) : val(_val), par(0), to(0) {
		to = new node;
		memset(go, 0, sizeof(go));
	}
} *root, *last;

inline void extend(int w) {
	State *p = last;
	State *np = new State(p->val + 1);
	while (p && p->go[w] == 0)
		p->go[w] = np, p = p->par;
	if (p == 0) {
		np->par = root;
		LCT::link_to(np->to, root->to);
	} else {
		State *q = p->go[w];
		if (q->val == p->val + 1) {
			np->par = q;
			LCT::link_to(np->to, q->to);
		} else {
			State *nq = new State(p->val + 1);
			memcpy(nq->go, q->go, sizeof(q->go));
			nq->par = q->par;
			LCT::link_to_nq(nq->to, q->par->to);
			q->par = np->par = nq;
			LCT::cut_to(q->to, nq->to);
			LCT::link_to(np->to, nq->to);
			while (p && p->go[w] == q)
				p->go[w] = nq, p = p->par;
		}
	}
	last = np;
}

inline void fix(char *s, int la) {
	int len = strlen(s);
	for(int i = 0; i < len; ++i) {
		la = (la * 131 + i) % len;
		swap(s[i], s[la]);
	}
}

inline int find(char *s) {
	State *tmp = root;
	int len = strlen(s);
	for(int i = 0; i < len; ++i)
		if (tmp->go[s[i] - 'A']) tmp = tmp->go[s[i] - 'A'];
		else return 0;
	LCT::access(tmp->to);
	LCT::splay(tmp->to);
	return tmp->to->r;
}

int q, la;
char s[3000003], w[103];

int main() {
	null = new node; *null = node();
	root = last = new State(0);
	root->to = new node;
	scanf("%d", &q);
	scanf("%s", s + 1);
	int len = strlen(s + 1), ans;
	for(int i = 1; i <= len; ++i)
		extend(s[i] - 'A');
	
	while (q--) {
		scanf("%s%s", w, s);
		len = strlen(s);
		fix(s, la);
		if (w[0] == 'Q') {
			ans = find(s);
			printf("%d\n", ans);
			la ^= ans;
		} else {
			for(int i = 0; i < len; ++i)
				extend(s[i] - 'A');
		}
	}
	return 0;
}
posted @ 2016-09-30 16:39  abclzr  阅读(289)  评论(0编辑  收藏  举报