• 【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
    ", ans);
    			la ^= ans;
    		} else {
    			for(int i = 0; i < len; ++i)
    				extend(s[i] - 'A');
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    一个6亿的表a,一个3亿的表b,通过外间tid关联,你如何最快的查询出满足条件的第50000到第50200中的这200条数据记录
    MySQL复制表的方式以及原理和流程
    Python里面如何拷贝一个对象
    python中*args,**kwargs
    Python删除list里面的重复元素的俩种方法
    Python是如何进行内存管理
    python中lambda函数
    python中filter(),reduce()函数
    python中map()函数用法
    重磅发布:阿里开源 OpenJDK 长期支持版本 Alibaba Dragonwell
  • 原文地址:https://www.cnblogs.com/abclzr/p/5924219.html
Copyright © 2020-2023  润新知