【伸展树(splay)】[JSOI2008][HYSBZ/BZOJ1014]火星人prefix
2016-02-12 23:40
603 查看
题目链接
分析
这道题有修改操作,显然不能使用后缀数组等数据结构。我们可以用hash值来判断两个字符串是否相同,所以,我们可以用splay来维护出以当前字符为根的字符串的hash值,二分长度来求出LCQ(x,y)的值。
代码
这是top-down的splay[code]#include<cstdio> #include<algorithm> #include<cstring> #define P 67 #define MOD 1000000007 using namespace std; #define MAXN 100000 int hash_pow[MAXN+10],m,n; char s[MAXN+10]; void Read(int &x){ char c; while(c=getchar(),c!=EOF) if(c>='0'&&c<='9'){ x=c-'0'; while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0'; ungetc(c,stdin); return; } } struct node{ int size,val,h; node *ch[2]; }tree[MAXN+10],*tcnt=tree,*nil=tree,*root=nil; void init(node *x){ x->val=x->size=x->h=0; x->ch[0]=x->ch[1]=nil; } inline void update(node *p){ p->size=p->ch[0]->size+p->ch[1]->size+1; p->h=((1ll*p->ch[0]->h*P+p->val)%MOD*hash_pow[p->ch[1]->size]%MOD+p->ch[1]->h)%MOD; } void single_Rotate(bool d){ node *x=root->ch[!d]; root->ch[!d]=nil->ch[!d]; nil->ch[!d]=root; root=x; } void double_Rotate(bool d){ node *x=root->ch[!d],*y=x->ch[!d]; root->ch[!d]=x->ch[d]; x->ch[d]=root; x->ch[!d]=nil->ch[!d]; nil->ch[!d]=x; update(root); root=y; } void finish(){ node *x,*y; for(int d=0;d<2;d++){ x=nil->ch[!d]; while(x!=nil){ y=x->ch[!d]; x->ch[!d]=root->ch[d]; root->ch[d]=x; update(x); x=nil->ch[!d]=y; } } update(root); } template<class T> void search_pos(T pos){ bool d,dd; node *x; while(root!=nil){ if(root->ch[0]->size+1==pos) return; if(pos<root->ch[0]->size+1) d=1; else d=0,pos-=root->ch[0]->size+1; x=root->ch[!d]; if(x==nil||x->ch[0]->size+1==pos){ single_Rotate(d); return; } if(pos<x->ch[0]->size+1) dd=1; else dd=0,pos-=x->ch[0]->size+1; if(d==dd) double_Rotate(d); else single_Rotate(d),single_Rotate(dd); } } void read(){ scanf("%s",s); n=strlen(s); init(nil); for(int i=0;i<n;i++){ single_Rotate(0); init(root=++tcnt); root->val=s[i]-'a'+1; } finish(); } inline int Get_hash(int pos){ if(pos>root->size) return 0; search_pos(pos); finish(); return (1ll*root->val*hash_pow[root->ch[1]->size]%MOD+root->ch[1]->h)%MOD; } bool check(int x,int y,int len){ int a,b; a=((Get_hash(x)-Get_hash(x+len))%MOD+MOD)%MOD; b=(1ll*(Get_hash(y)-Get_hash(y+len))%MOD*hash_pow[y-x]%MOD+MOD)%MOD; return a==b; } int partition(int x,int y,int l,int r){ int mid; while(l<r){ mid=(l+r+1)>>1; if(check(x,y,mid)) l=mid; else r=mid-1; } return l; } void repla(int pos,int val){ search_pos(pos); root->val=val; finish(); } void insert(int pos,int val){ search_pos(pos+0.5); init(root=++tcnt); root->val=val; finish(); } void solve(){ Read(m); char c[20]; int x,y; while(m--){ scanf("%s",c); if(c[0]=='Q'){ Read(x),Read(y); if(x>y) swap(x,y); printf("%d\n",partition(x,y,0,root->size-y+1)); } else if(c[0]=='R'){ Read(x),scanf("%s",c); repla(x,c[0]-'a'+1); } else{ Read(x),scanf("%s",c); insert(x,c[0]-'a'+1); } } } void prepare(){ hash_pow[0]=1; for(int i=1;i<=MAXN;i++) hash_pow[i]=1ll*hash_pow[i-1]*P%MOD; } int main() { prepare(); read(); solve(); }
相关文章推荐
- js三元运算符 js运算符优先级
- knockoutjs九 submit绑定
- knockoutjs八 event绑定
- js随机生成26个大小写字母
- JavaScript面向对象简介
- JS瀑布流技术总结
- 手机图片js在线剪切
- JS固定侧边栏教程总结
- .Net后台使用RegisterClientScriptBlock和RegisterStartupScript调用前台的JS 区别
- javascript基础:字符串自动转换为数字类型
- JavaScript【基础篇】
- JavaScript学习过程
- JSTL与EL
- ajax 提交post get 数据,得到json结果解析
- js 中对象--对象结构(原型链基础解析)
- JAVASCRIPT的一些知识点梳理
- [bzoj1017]: [JSOI2008]魔兽地图DotR
- JavaScript实现点击单元格改变背景色的方法
- JavaScript实现弹出模态窗体并接受传值的方法
- JavaScript判断表单为空及获取焦点的方法