BZOJ 2258 pku2758 Checking the Text 文本校对 Splay+Hash+二分

73 篇文章 0 订阅
8 篇文章 0 订阅

题目大意:初始给出一个字符串,下面有一些操作,可以在一个地方加一个字符,询问从两个地方开始最长的匹配长度。


思路:Splay维护Hash值,询问的时候二分一下就行了。它条件给的比较恶心,注意处理的时候按照他说的做就行了。


CODE:

#define _CRT_SECURE_NO_DEPRECATE

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 51010
#define BASE 2333
using namespace std;
#define WORKPATH (root->son[1]->son[0])

unsigned long long power[MAX];

struct SplayTree{
	int val,size;
	unsigned long long hash;
	SplayTree *son[2],*father;

	SplayTree(int _);
	SplayTree() {}
	void Combine(SplayTree *a,bool dir) {
		son[dir] = a;
		a->father = this;
	}
	bool Check() {
		return father->son[1] == this;
	}
	void PushUp() {
		size = son[0]->size + son[1]->size + 1;
		hash = son[0]->hash + val * power[son[0]->size] + son[1]->hash * power[son[0]->size + 1];
	}
}*root,none,*nil = &none,*src[MAX];
SplayTree :: SplayTree(int _) {
	val = hash = _;
	size = 1;
	son[0] = son[1] = nil;
}

void Pretreatment()
{
	power[0] = 1;
	for(int i = 1; i < MAX; ++i)
		power[i] = power[i - 1] * BASE;
	nil->son[0] = nil->son[1] = nil->father = nil;
}

char s[MAX];

SplayTree *BuildTree(int l,int r)
{
	if(l > r)	return nil;
	int mid = (l + r) >> 1;
	SplayTree *re = new SplayTree(s[mid]);
	src[mid] = re;
	re->Combine(BuildTree(l,mid - 1),false);
	re->Combine(BuildTree(mid + 1,r),true);
	re->PushUp();
	return re;
}

inline void Rotate(SplayTree *a,bool dir)
{
	SplayTree *f = a->father;
	f->son[!dir] = a->son[dir];
	f->son[!dir]->father = f;
	a->son[dir] = f;
	a->father = f->father;
	f->father->son[f->Check()] = a;
	f->father = a;
	f->PushUp();
	if(root == f)	root = a;
}

inline void Splay(SplayTree *a,SplayTree *aim)
{
	while(a->father != aim) {
		if(a->father->father == aim)
			Rotate(a,!a->Check());
		else if(!a->father->Check()) {
			if(!a->Check())
				Rotate(a->father,true),Rotate(a,true);
			else	Rotate(a,false),Rotate(a,true);
		}
		else {
			if(a->Check())
				Rotate(a->father,false),Rotate(a,false);
			else	Rotate(a,true),Rotate(a,false);
		}
	}
	a->PushUp();
}

SplayTree *Find(SplayTree *a,int k)
{
	if(a->son[0]->size >= k)	return Find(a->son[0],k);
	k -= a->son[0]->size;
	if(k == 1)	return a;
	return Find(a->son[1],k - 1);
}

int asks;
int length;

inline unsigned long long GetHash(int l,int len)
{
	int l_size;
	Splay(src[l],nil),l_size = root->son[0]->size + 1;
	if(l_size + len > length + 2)	throw false;
	Splay(Find(root,l_size - 1),nil);
	Splay(Find(root,l_size + len),root);
	return WORKPATH->hash;
}

inline bool Judge(int x,int y,int ans)
{
	unsigned long long l,r;
	try{
		l = GetHash(x,ans);
		r = GetHash(y,ans);
	}
	catch(bool) {
		return false;
	}
	return l == r;
}

int main()
{
	Pretreatment();
	scanf("%s",s + 1);
	length = strlen(s + 1);
	root = BuildTree(0,length + 1);
	root->father = nil;
	cin >> asks;
	for(int x,y,i = 1; i <= asks; ++i) {
		scanf("%s",s);
		if(s[0] == 'Q') {
			scanf("%d%d",&x,&y);
			int l = 0,r = length,ans = 0;
			while(l <= r) {
				int mid = (l + r) >> 1;
				if(Judge(x,y,mid))	l = mid + 1,ans = mid;
				else	r = mid - 1;
			}
			printf("%d\n",ans);
		}
		else {
			scanf("%s%d",s,&x);
			if(x > length)	x = length + 1;
			++length;
			Splay(Find(root,x),nil);
			Splay(Find(root,x + 1),root);
			root->son[1]->Combine(new SplayTree(s[0]),false);
			root->son[1]->PushUp();
			root->PushUp();
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值