zoj 3533 Gao the String I(伸展树+字符串hash)
来源:互联网 发布:2017网络名词 编辑:程序博客网 时间:2024/05/02 01:36
题意:给出一个长度为n的串,有四种操作:
①翻转区间[a,b]②把第p个字符改成c③求以a和b开头的最大公共前缀④求当前串的最大回文子串
思路:维护序列当然伸展树比较方便啦~求LCP可以通过字符串hash,求最大回文比较少,可以直接Manacher搞定。之前做了类似的,所以思路上完全没问题,不过犯了二,debug了好久。。。
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;typedef unsigned long long Ull;const int maxn=100000+10;const int rp=233;Ull hash[maxn][2],pw[maxn];int ch[maxn][2],size[maxn],val[maxn],flip[maxn];int pre[maxn],p[maxn<<1],root,tot,cnt;char str[maxn],s[maxn<<1];void NewNode(int &rt,int fa,int v){ rt=++tot; ch[rt][0]=ch[rt][1]=flip[rt]=0; pre[rt]=fa;size[rt]=1; hash[rt][0]=hash[rt][1]=val[rt]=v;}inline void PushUp(int rt){ int ls=ch[rt][0],rs=ch[rt][1]; size[rt]=size[ls]+size[rs]+1; hash[rt][0]=hash[ls][0]+val[rt]*pw[size[ls]]+hash[rs][0]*pw[(size[ls]+1)]; hash[rt][1]=hash[rs][1]+val[rt]*pw[size[rs]]+hash[ls][1]*pw[(size[rs]+1)];}inline void fson(int rt){ if(!rt) return ; swap(ch[rt][0],ch[rt][1]); swap(hash[rt][0],hash[rt][1]); flip[rt]^=1;}void PushDown(int rt){ if(flip[rt]) { fson(ch[rt][0]); fson(ch[rt][1]); flip[rt]=0; }}void Rotate(int x,int kind){ int y=pre[x]; PushDown(y);PushDown(x); ch[y][kind^1]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y]; ch[x][kind]=y; pre[y]=x; PushUp(y);}void Splay(int rt,int goal){ PushDown(rt); while(pre[rt]!=goal) { int y=pre[rt]; if(pre[y]==goal) Rotate(rt,ch[y][0]==rt); else { int kind=ch[pre[y]][0]==y; if(ch[y][kind]==rt) { Rotate(rt,kind^1); Rotate(rt,kind); } else { Rotate(y,kind); Rotate(rt,kind); } } } PushUp(rt); if(goal==0) root=rt;}void RotateTo(int k,int goal){ int rt=root; PushDown(rt); while(size[ch[rt][0]]!=k) { if(size[ch[rt][0]]>k) rt=ch[rt][0]; else { k-=(size[ch[rt][0]]+1); rt=ch[rt][1]; } PushDown(rt); } Splay(rt,goal);}void Modify(int k,int v){ RotateTo(k-1,0); RotateTo(k+1,root); int rt=ch[ch[root][1]][0]; hash[rt][0]=hash[rt][1]=val[rt]=v; PushUp(ch[root][1]); PushUp(root);}void Reverse(int L,int R){ if(L>R) swap(L,R); RotateTo(L-1,0); RotateTo(R+1,root); fson(ch[ch[root][1]][0]); PushUp(ch[root][1]); PushUp(root);}bool check(int x,int y,int len){ Ull xval,yval; RotateTo(x-1,0); if(size[ch[root][1]]-1<len) return 0; RotateTo(x+len,root); int rt=ch[ch[root][1]][0]; xval=hash[rt][flip[rt]]; RotateTo(y-1,0); if(size[ch[root][1]]-1<len) return 0; RotateTo(y+len,root); rt=ch[ch[root][1]][0]; yval=hash[rt][flip[rt]]; return xval==yval;}int Lcp(int x,int y){ if(x>y) swap(x,y); int l=1,r=size[root]-1; if(!check(x,y,1)) return 0; while(r-l>1) { int m=(l+r)>>1; if(check(x,y,m)) l=m; else r=m; } return l;}void dfs(int rt){ if(rt) { PushDown(rt); dfs(ch[rt][0]); str[cnt++]=val[rt]; dfs(ch[rt][1]); }}int Palindrome(){ cnt=0; dfs(root); str[cnt-1]=0; int n=0; s[n++]='$';s[n++]='#'; for(int i=1;str[i];++i) { s[n++]=str[i]; s[n++]='#'; } int mx=0,id=0,ans=0; p[0]=0; for(int i=1;i<n;++i) { p[i]=1; if(mx>i) p[i]=min(p[id*2-i],mx-i); while(s[i+p[i]]==s[i-p[i]]) p[i]++; if(i+p[i]>mx) { mx=i+p[i]; id=i; } if(p[i]>ans) ans=p[i]; } return ans-1;}void build(int l,int r,int &rt,int fa){ if(l>r) return ; int m=(l+r)>>1; NewNode(rt,fa,str[m]); build(l,m-1,ch[rt][0],rt); build(m+1,r,ch[rt][1],rt); PushUp(rt);}void Init(int n){ ch[0][0]=ch[0][1]=pre[0]=0; hash[0][0]=hash[0][1]=0; flip[0]=val[0]=size[0]=0; root=tot=0; NewNode(root,0,0); NewNode(ch[root][1],root,0); build(0,n-1,ch[ch[root][1]][0],ch[root][1]); PushUp(ch[root][1]); PushUp(root);}int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); pw[0]=1; for(int i=1;i<maxn;++i) pw[i]=pw[i-1]*rp; int n,m,a,b; char qs[15]; while(~scanf("%s",str)) { n=strlen(str); Init(n); scanf("%d",&m); while(m--) { scanf("%s",qs); if(qs[0]=='P') printf("%d\n",Palindrome()); else if(qs[0]=='M') { scanf("%d%s",&a,qs); Modify(a,qs[0]); } else { scanf("%d%d",&a,&b); if(qs[0]=='R') Reverse(a,b); else printf("%d\n",Lcp(a,b)); } } } return 0;}
0 0
- zoj 3533 Gao the String I(伸展树+字符串hash)
- ZOJ3533-Gao the String I
- ZOJ 3535 Gao the String II
- zoj3533 Gao the String I(splay)
- Acdreamoj1116(Gao the string!)字符串hash+二分+矩阵快速幂
- zoj 3535 Gao the String II(ac自动机+dp)
- zoj 3535 Gao the String II(AC自动机+DP)
- Zoj 3535 Gao the String II (AC自动机+dp)
- zoj 3535 Gao the String II (ac自动机+dp)
- ZOJ 3647 Gao the Grid
- zoj 3672 Gao The Sequence
- ZOJ 3647 Gao the Grid
- zoj - 3672 - Gao The Sequence
- ZOJ 3672 Gao The Sequence
- zoj 3647 Gao the Grid
- ZOJ-3647 Gao the Grid
- ZOJ 3647 Gao the Grid
- acdream 1116 Gao the string!
- 程序员在 5 月 20 日这天特别的表白方式
- 从数组中查找给定数的下标
- 项目管理之美摘录
- OpenGL中的空间变换
- linux 线程 (1)
- zoj 3533 Gao the String I(伸展树+字符串hash)
- 开发指南专题六:JEECG微云快速开发平台代码生成
- 如何对td/tr/table进行disabled设置
- Linux下利用ICMP协议实现ping命令
- Android View与GroupView原理以及其子类描述
- Eclipse查询MySql、添加中文乱码问题
- Leetcode 二分查找 Search a 2D Matrix
- iOS进行单元测试OCUnit+xctool - yingkong1987
- window8 激活工具