bzoj 1014 [JSOI2008]火星人prefix(splay+hash)
2016-03-20 15:17
627 查看
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=1014
【题意】
给定一个字符串,要求提供修改一个字符,插入一个字符,查询两个后缀LCP的功能。
【思路】
splay维护字符串的哈希值。因为要提供区间,splay采用先查找后调整至根的写法。
一个结点的hash值为:
ch[0]->h * X^(ch[1]->s+1)+v * X^(ch[1]->s)+ch[1]->h
对于一个询问每次二分长度,提取区间后比较hash值即可。
需要注意的是splay要提前在区间的左右两边各加上一个节点,不然会调用到null。
ull自然溢出相当于模2^64。
【代码】
http://www.lydsy.com/JudgeOnline/problem.php?id=1014
【题意】
给定一个字符串,要求提供修改一个字符,插入一个字符,查询两个后缀LCP的功能。
【思路】
splay维护字符串的哈希值。因为要提供区间,splay采用先查找后调整至根的写法。
一个结点的hash值为:
ch[0]->h * X^(ch[1]->s+1)+v * X^(ch[1]->s)+ch[1]->h
对于一个询问每次二分长度,提取区间后比较hash值即可。
需要注意的是splay要提前在区间的左右两边各加上一个节点,不然会调用到null。
ull自然溢出相当于模2^64。
【代码】
#include<set> #include<cmath> #include<queue> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define trav(u,i) for(int i=front[u];i;i=e[i].nxt) #define FOR(a,b,c) for(int a=(b);a<=(c);a++) using namespace std; typedef long long ll; typedef unsigned long long ull; const int N = 5e5+10; const int X = 27; ll read() { char c=getchar(); ll f=1,x=0; while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x*f; } char s ; int n,q; ull powx ; struct Node* null; struct Node { int s,v; ull h; Node* ch[2]; int cmp(int k) { if(k==ch[0]->s+1) return -1; return k<=ch[0]->s? 0:1; } void init(int x) { v=h=x; s=1; ch[0]=ch[1]=null; } void maintain() { s=ch[0]->s+ch[1]->s+1; h=ch[0]->h*powx[ch[1]->s+1]+v*powx[ch[1]->s]+ch[1]->h; } } *root,nodepool ; int nodesz=0; void rot(Node* &o,int d) { Node* k=o->ch[d^1]; o->ch[d^1]=k->ch[d]; k->ch[d]=o; o->maintain(),k->maintain(); o=k; } void splay(Node*& o,int k) { int d=o->cmp(k); if(d==1) k-=o->ch[0]->s+1; if(d!=-1) { Node* p=o->ch[d]; int d2=p->cmp(k),k2=(d2==0?k:k-p->ch[0]->s-1); if(d2!=-1) { splay(p->ch[d2],k2); if(d==d2) rot(o,d^1); else rot(o->ch[d],d); } rot(o,d^1); } } //return range (l,r] //加过点后 s[l,r]=range(l,r+1) Node*& range(int l,int r) { splay(root,l); splay(root->ch[1],r-l+1); return root->ch[1]->ch[0]; } Node* build(int l,int r) { if(r<l) return null; int mid=l+r>>1; Node* o=&nodepool[++nodesz]; o->init(s[mid]-'a'+1); o->ch[0]=build(l,mid-1); o->ch[1]=build(mid+1,r); o->maintain(); return o; } void insert(int p,int v) { splay(root,p+1); Node* o=&nodepool[++nodesz]; o->init(v); o->ch[0]=root->ch[0]; o->ch[1]=null; o->maintain(); root->ch[0]=o; root->maintain(); } void change(int p,int v) { splay(root,p); root->v=v; root->maintain(); } int main() { //freopen("in.in","r",stdin); //freopen("out.out","w",stdout); null=new Node(); scanf("%s",s+1); int n=strlen(s+1); s[0]='z'+1; s[++n]='z'+1; s[n+1]='\0'; scanf("%d",&q); powx[0]=1; FOR(i,1,n+q) powx[i]=powx[i-1]*X; root=build(0,n); while(q--) { char op[2],val[2]; int x,y; scanf("%s%d",op,&x); if(op[0]=='R') { scanf("%s",val); change(x+1,val[0]-'a'+1); } else if(op[0]=='I') { scanf("%s",val); insert(x+1,val[0]-'a'+1); } else { scanf("%d",&y); int len=root->s,L=0,R=0; R=min(len-y-1,len-x-1); while(L<R) { int M=L+(R-L+1)/2; ull H=range(x,x+M)->h; H-=range(y,y+M)->h; if(!H) L=M; else R=M-1; } printf("%d\n",L); } } return 0; }
相关文章推荐
- FastJson构造json串空的问题
- cesium js学习一加载三维模型
- 真实经纬度(gps)转成百度坐标的js方法
- 牛客网 JS能力测评经典题
- .使用json作为返回值并遍历该值
- JavaScript中正则表达式test()、exec()、match() 方法
- JavaScript入门知识点整理
- ExtJs之VTYPE验证
- SeaJS之use函数
- ExtJs之FieldSet和FieldContainer
- Javascript中的原型
- <香港科技大学html+css+js课堂笔记>week1--html部分
- 用GSON解析Json格式数据
- 还在抱怨JS文件里没有智能提示吗, VS10以及以上都可以 .NET
- 你该知道的json解析
- JS实现10-0的倒计时动画效果
- JS中的冒泡排序法
- JSZX_HC_2016_R5
- 课外转载-js验证表单
- js 实现实时时钟