题目大意:初始给出一个字符串,下面有一些操作,可以在一个地方加一个字符,询问从两个地方开始最长的匹配长度。
思路: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;
}