[bzoj2555]SubString
2016-03-09 18:18
344 查看
题目大意
要求兹瓷两个操作1、在字符串后插入字符串变为新的字符串
2、询问字符串内某字符串的出现次数
LCT维护SAM
对于询问字符串出现次数而且要兹瓷在尾部添加字符,容易想到是SAM,根据pre指针建树,然后用LCT维护这颗pre树即可。#include<cstdio> #include<cstring> #include<algorithm> #define fo(i,a,b) for(i=a;i<=b;i++) using namespace std; typedef int ll; const ll maxn=600000+10; ll father[maxn*2],tree[maxn*2][2],sta[maxn*2],pp[maxn*2]; long long size[maxn*2],add[maxn*2]; ll pre[maxn*2],g[maxn*2][26],step[maxn*2]; char s[maxn]; bool czy; char ch; ll i,j,k,l,t,n,m,mask,tot,ans,last,top; void get_s(ll mask) { scanf("%s",s+1); n=strlen(s+1); fo(i,0,n-1) { mask=(mask*131+i)%n; swap(s[i+1],s[mask+1]); } } ll pd(ll x){ return tree[father[x]][1]==x; } void clear(ll x){ if (add[x]){ size[tree[x][0]]+=add[x]; add[tree[x][0]]+=add[x]; size[tree[x][1]]+=add[x]; add[tree[x][1]]+=add[x]; add[x]=0; } } void remove(ll x,ll y){ top=0; while (x!=y){ sta[++top]=x; x=father[x]; } while (top){ clear(sta[top]); top--; } } void rotate(ll x){ ll y=father[x],z=pd(x); father[x]=father[y]; if (father[y]) tree[father[y]][pd(y)]=x; tree[y][z]=tree[x][1-z]; if (tree[x][1-z]) father[tree[x][1-z]]=y; tree[x][1-z]=y; father[y]=x; if (pp[y]) pp[x]=pp[y],pp[y]=0; } void splay(ll x,ll y){ remove(x,y); while (father[x]!=y){ if (father[father[x]]!=y) if (pd(x)==pd(father[x])) rotate(father[x]);else rotate(x); rotate(x); } } void access(ll x){ ll y; splay(x,0); //clear(x); if (tree[x][1]) pp[tree[x][1]]=x; father[tree[x][1]]=0; tree[x][1]=0; while (pp[x]){ y=pp[x]; splay(y,0); //clear(y); if (tree[y][1]) pp[tree[y][1]]=y; father[tree[y][1]]=0; tree[y][1]=x; father[x]=y; pp[x]=0; splay(x,0); } } void link(ll x,ll y){ splay(x,0); access(y); splay(y,0); size[y]+=size[x]; add[y]+=size[x]; pp[x]=y; } void cut(ll x,ll y){ splay(x,0); access(y); splay(y,0); size[y]-=size[x]; add[y]-=size[x]; pp[x]=0; } void insert(char ch){ ll np=++tot; size[np]=1; step[np]=step[last]+1; ll p=last; while (p&&g[p][ch-'A']==0){ g[p][ch-'A']=np; p=pre[p]; } if (!p){ pre[np]=1; link(np,1); } else{ ll q=g[p][ch-'A']; if (step[q]==step[p]+1){ pre[np]=q; link(np,q); } else{ ll nq=++tot; step[nq]=step[p]+1; pre[nq]=pre[q]; link(nq,pre[q]); cut(q,pre[q]); pre[q]=nq; link(q,nq); int i; fo(i,0,25) g[nq][i]=g[q][i]; pre[np]=nq; link(np,nq); while (p&&g[p][ch-'A']==q){ g[p][ch-'A']=nq; p=pre[p]; } } } last=np; } int get(){ int x=1,i; fo(i,1,n){ if (!x) return 0; x=g[x][s[i]-'A']; } if (!x) return 0; splay(x,0); return size[x]; } char get_c(){ char ch=getchar(); while (ch<'A'||ch>'Z') ch=getchar(); return ch; } int main(){ //freopen("2555.in","r",stdin);freopen("2555.out","w",stdout); scanf("%lld",&m); pre[last=tot=1]=0; scanf("%s",s+1); n=strlen(s+1); fo(i,1,n) insert(s[i]); mask=0; while (m--){ ch=get_c(); if (ch=='A') czy=1;else czy=0; fo(i,1,4-2*czy) ch=get_c(); get_s(mask); if (czy){ fo(i,1,n) insert(s[i]); } else{ ans=get(); mask^=ans; printf("%lld\n",ans); } } //fclose(stdin);fclose(stdout); return 0; }
相关文章推荐
- NSDate和NSString的相互转换
- myeclipse 中如何更换 SVN账户
- MAVEN 执行一个main函数的命令
- Cannot convert '0000-00-00 00:00:00' to TIMESTAMP
- OC中NSString的操作
- FBO
- Ios开发之 -- js和ios的交互
- MFC判断鼠标坐标是否在控件内
- vim命令集合
- 判断素数 is_prime()
- 大数据高手之路
- 阿里移动安全发布《2015物联网安全年报》,威胁攻击日益凸显
- 获取地理位置及计算距离
- Shiro学习--与SpringMVC整合(数据库,Shiro注解和Shiro标签)
- 一起看代码来玩玩QT之24 AudioPlayer
- iOS NSOperation学习笔记
- php-fpm – 启动参数及重要配置详解
- markdown 语法
- oracle物理DG管理-redo数据传输,应用与三种模式
- 一张大图总结数据结构与算法