题目
http://www.lydsy.com/JudgeOnline/problem.php?id=1014
题解
故事是这样的:一开始我用了双模哈希,交上去老TLE。
我觉得应该不是常数的问题,于是各种调试,还是T。
然后我又make了好多大数据,去hzwer.com下载了黄学长的代码和我的比较,发现黄学长总比我快那么一点点,看了黄学长的代码发现他是单模哈希。
然后我交了黄学长的代码,发现他10s卡着过了!
于是我就各种优化常数,优化。。。优化。。。。改成了模质数+自然溢出
然而还是T。
最后我愤怒的把程序改成了单模哈希。结果卡着10s过了。。。。。。汗
真是无语。
哦忘了写题解。其实就是用splay维护一个字符串序列。
对于R操作,直接找那个点,splay到根,更改值。
对于I操作,找到编号为x和x+1的点,在中间插入(这里写麻烦了,我用了pos和tag,其实一个size就能够替代)。然后update。
对于Q操作,查询x和y的最长公共前缀。首先二分答案,然后判断就是直接用splay取出这两段区间的hash值,判断是否相等。
表示:单模hash冲突的概率也这么小吗??以后不写双模了好不好?
代码
//splay+hash
#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 110000
#define ll long long
#define P 4894651LL
#define root RT->lch
using namespace std;
struct node
{
ll size, hash, pos, tag, c;
node *lch, *rch, *f;
node(){size=1;hash=pos=tag=c=0;lch=rch=f=0;}
}*RT, nd[maxn];
ll mi26[2][maxn], length, nodetot;
char s[maxn];
void reads(char *s)
{
char c=getchar();
ll cnt=0;
while((c>='a' and c<='z') or c=='Q' or c=='R' or c=='I')s[cnt++]=c,c=getchar();
s[cnt]=0;
}
ll read(ll x=0)
{
char c=getchar();
while(c<48 or c>58)c=getchar();
while(c>=48 and c<=58)x=x*10+c-48,c=getchar();
return x;
}
inline void pushdown(node *p)
{
if(p==0)return;
if(p->tag==0)return;
p->pos+=p->tag;
if(p->lch)p->lch->tag+=p->tag;
if(p->rch)p->rch->tag+=p->tag;
p->tag=0;
}
inline void update(node *p)
{
if(p==0)return;
ll hash1, hash2, len=p->rch?p->rch->size:0;
hash1=p->lch?p->lch->hash:0, hash2=p->rch?p->rch->hash:0;
p->hash=(hash1*mi26[0][len+1]+p->c*mi26[0][len]+hash2)%P;
p->size=(p->lch?p->lch->size:0)+1+len;
}
void zig(node *x)
{
node *y=x->f, *z=y->f;
pushdown(y),pushdown(x);
if(z->lch==y)z->lch=x;
else z->rch=x;
x->f=z;
if(x->rch)x->rch->f=y;y->lch=x->rch;
x->rch=y;y->f=x;
update(y),update(x);
}
void zag(node *x)
{
node *y=x->f, *z=y->f;
pushdown(y),pushdown(x);
if(z->lch==y)z->lch=x;
else z->rch=x;
x->f=z;
if(x->lch)x->lch->f=y;y->rch=x->lch;
x->lch=y;y->f=x;
update(y),update(x);
}
void rotate(node *p){if(p->f->lch==p)zig(p);else zag(p);}
void splay(node *x, node *F)
{
node *y, *z;
while(x->f!=F)
{
y=x->f;z=y->f;
if(z==F){rotate(x);break;}
if((z->lch==y&&y->lch==x) || (z->rch==y&&y->rch==x))rotate(y),rotate(x);
else rotate(x),rotate(x);
}
}
node* find(node *x, ll num)
{
pushdown(x);
if(x->pos==num)return x;
else if(x->pos<num)return find(x->rch,num);
else return find(x->lch,num);
}
bool check(ll l1, ll r1, ll l2, ll r2)
{
if(l1>r1)return true;
ll h1, h2;
node *p1, *p2;
l1--,l2--;r1++,r2++;
p1=find(root,l1),p2=find(root,r1);
splay(p1,RT),splay(p2,p1);
h1=p2->lch->hash;
p1=find(root,l2),p2=find(root,r2);
splay(p1,RT),splay(p2,p1);
h2=p2->lch->hash;
return h1==h2;
}
ll LCQ(ll x, ll y)
{
ll l, r, mid;
l=0,r=min(length-x+1,length-y+1),mid=(l+r+1)>>1;
while(l<r)
{
if(check(x,x+mid-1,y,y+mid-1))l=mid;
else r=mid-1;
mid=(l+r+1)>>1;
}
return l;
}
void input()
{
node *p, *p1, *p2;
ll i;
reads(s+1);
length=strlen(s+1);
RT=nd+nodetot++;
p1=nd+nodetot++;
p1->pos=0;p1->c=p1->hash=-1;
RT->lch=p1;p1->f=RT;
p2=nd+nodetot++;
p2->pos=length+1;p2->c=p2->hash=-1;
p1->rch=p2;p2->f=p1;
mi26[0][0]=mi26[1][0]=1;
for(i=1;i<maxn;i++)
mi26[0][i]=mi26[0][i-1]*26%P,mi26[1][i]=mi26[1][i-1]*26;
for(i=1;i<=length;i++)
{
p=nd+nodetot++;
p->c=p->hash=s[i]-97;
p->pos=i;
splay(p1,RT);
p2->lch=p;p->f=p2;
update(p2),update(p1);
p1=p;
}
}
void solve()
{
ll x, y, M;
node *p1, *p2, *p;
char d[3], type[3];
M=read();
while(M--)
{
reads(type);
x=read();
if(*type=='Q')
{
y=read();
printf("%lld\n",LCQ(x,y));
}
else if(*type=='R')
{
reads(d);
p=find(root,x);
splay(p,RT);
p->c=*d-97;
update(p);
}
else
{
reads(d);
p1=find(root,x),p2=find(root,x+1);
p=nd+nodetot++;
p->c=p->hash=*d-97;
p->pos=x+1;
splay(p1,RT),splay(p2,p1);
p2->tag++;
pushdown(p2);
p2->lch=p;p->f=p2;
update(p2),update(p1);
length++;
}
}
}
int main()
{
input();
solve();
return 0;
}