• 【BZOJ 1014】【JSOI 2008】火星人prefix


    看了《Hash在信息学竞赛中的一类应用》中的例题3,这道题很类似啊,只不过没有删点和区间翻转。

    用Splay维护字符串哈希,加点改点什么的就不用说了,查询时二分答案,这样时间复杂度是$O(mlog^2 n)$的

    论文的例题3中删点很简单,和插点一样,不用说了,区间翻转只要打一个翻转标记,维护正序hash和逆序hash,翻转时交换两个hash值即可。

    对拍终于成功了QAQ,插点时孩子不认父亲TwT又手残了~

    《Hash在信息学竞赛中的一类应用》中还提到了块状链表的做法,都很易懂:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 100003;
    const int p = 9875321;
    
    int P[N];
    struct node *null;
    struct node {
    	node *ch[2], *fa;
    	int k, s, ha;
    	node (int _k = 0) {k = _k; s = 1; ha = _k; ch[0] = ch[1] = fa = null;}
    	void setc(node *r, bool c) {this->ch[c] = r; r->fa = this;}
    	bool pl() {return fa->ch[1] == this;}
    	void count() {
    		s = ch[0]->s + ch[1]->s + 1;
    		ha = ((ch[0]->ha + 1ll * k * P[ch[0]->s]) % p + 1ll * ch[1]->ha * P[ch[0]->s + 1] % p) % p;
    	}
    } *root;
    
    int n, m;
    char s[N];
    
    namespace Splay {
    	node *Build(int l, int r) {
    		if (l > r) return null;
    		int mid = (l + r) >> 1;
    		node *t = new node(s[mid] - 'a');
    		t->ch[0] = Build(l, mid - 1); t->setc(t->ch[0], 0);
    		t->ch[1] = Build(mid + 1, r); t->setc(t->ch[1], 1);
    		t->count();
    		return t;
    	}
    	void init() {
    		P[0] = 1; for(int i = 1; i < N; ++i) P[i] = P[i - 1] * 26 % p;
    		null = new node; null->s = 0; null->ch[0] = null->ch[1] = null->fa = null;
    		scanf("%s", s + 1); n = strlen(s + 1); root = Build(1, n);
    	}
    	void rotate(node *r) {
    		node *f = r->fa;
    		bool c = r->pl();
    		if (f != root) f->fa->setc(r, f->pl());
    		else root = r, r->fa = null;
    		f->setc(r->ch[!c], c);
    		r->setc(f, !c);
    		f->count();
    	}
    	void splay(node *r, node *tar = null) {
    		for(; r->fa != tar; rotate(r))
    			if (r->fa->fa != tar) rotate(r->pl() == r->fa->pl() ? r->fa : r);
    		r->count();
    	}
    	node *kth(int k) {
    		node *r = root;
    		while (1) {
    			if (r->ch[0]->s >= k) r = r->ch[0];
    			else if (r->ch[0]->s + 1 >= k) return r;
    			else k -= (r->ch[0]->s + 1), r = r->ch[1];
    		}
    	}
    	int hash(int l, int r) {
    		if (l == 1 && r == n) return root->ha;
    		else if (l == 1) {splay(kth(r + 1)); return root->ch[0]->ha;}
    		else if (r == n) {splay(kth(l - 1)); return root->ch[1]->ha;}
    		else {splay(kth(l - 1)); splay(kth(r + 1), root); return root->ch[1]->ch[0]->ha;}
    	}
    	void QQ(int l, int r) {
    		int left = 0, right = root->s - max(l, r) + 1, mid;
    		while (left < right) {
    			mid = (left + right + 1) >> 1;
    			if (hash(l, l + mid - 1) == hash(r, r + mid - 1)) left = mid;
    			else right = mid - 1;
    		}
    		printf("%d
    ", left); return;
    	}
    	void RR(int k, int num) {
    		node *r = kth(k);
    		r->k = num;
    		splay(r);
    	}
    	void II(int k, int num) {
    		if (k == 0) {
    			node *r = root;
    			while (r->ch[0] != null) r = r->ch[0];
    			r->setc(new node(num), 0);
    			splay(r->ch[0]);
    		} else {
    			splay(kth(k));
    			if (k == n) {
    				root->setc(new node(num), 1);
    				splay(root->ch[1]);
    			} else {
    				splay(kth(k + 1), root);
    				root->ch[1]->setc(new node(num), 0);
    				splay(root->ch[1]->ch[0]);
    			}
    		}
    		++n;
    	}
    }
    
    int main() {
    	Splay::init();
    	scanf("%d", &m);
    	char c; int x, y;
    	while (m--) {
    		for(c = getchar(); c < 'A' || c > 'Z'; c = getchar());
    		switch (c) {
    			case 'Q':
    				scanf("%d%d", &x, &y);
    				Splay::QQ(x, y);
    			break;
    			case 'R':
    				scanf("%d", &x); for(c = getchar(); c < 'a' || c > 'z'; c = getchar());
    				Splay::RR(x, c - 'a');
    			break;
    			case 'I':
    				scanf("%d", &x); for(c = getchar(); c < 'a' || c > 'z'; c = getchar());
    				Splay::II(x, c - 'a');
    			break;
    		}
    	}
    	return 0;
    }
    

    对拍大法好~

  • 相关阅读:
    周末郑州程序员朋友技术交流中的PPT
    WCF并发连接数的问题
    郑州.Net技术人员的招聘信息
    在路上
    Windows8体验(1)安装
    挖掘0day打进不同学校
    记一次绕过宝塔防火墙的BC站渗透
    一次实战中对tp5网站getshell方式的测试
    一次从弱口令到getshell
    一次HW实战
  • 原文地址:https://www.cnblogs.com/abclzr/p/5515710.html
Copyright © 2020-2023  润新知