SubString
来源:互联网 发布:淘宝上的汉斯格雅花洒 编辑:程序博客网 时间:2024/04/30 04:57
SubString
题目描述
http://www.lydsy.com/JudgeOnline/problem.php?id=2555
题解
这题等价于求sam上每个点的right集合大小。
每插入一个字符串,他的parent-tree上的所有父亲节点的right集合都要加1。
直接暴力加显然会TLE,所以我们可以用lct来维护parent-tree。
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<cmath>#include<algorithm>#define N 1200010#define M 3000010using namespace std;int Q,n,cnt=1,mask,ans,ch[N][30],fa[N],top[N],f[N];char s[M],str[10];struct node{int c[2],fa,size,tag;}t[N];class lct{ void add(int x,int y) { t[x].size+=y;t[x].tag+=y; } void pushdown(int x) { if(!t[x].tag)return; int lc=t[x].c[0],rc=t[x].c[1]; add(lc,t[x].tag);add(rc,t[x].tag); t[x].tag=0; } void rotate(int x,int k) { int y=t[x].fa,f=(t[t[y].fa].c[1]==y); pushdown(y);pushdown(x); if(!t[y].fa)fa[x]=fa[y]; t[x].fa=t[y].fa;t[t[y].fa].c[f]=x; t[y].c[k]=t[x].c[k^1];t[t[y].c[k]].fa=y; t[y].fa=x;t[x].c[k^1]=y; } public: void splay(int x) { pushdown(x); while(t[x].fa) { int y=t[x].fa,f=(t[y].c[1]==x); if(!t[y].fa)rotate(x,f); else { if((t[t[y].fa].c[1]==y)==f) rotate(y,f),rotate(x,f); else rotate(x,f),rotate(x,f^1); } } } void access(int x) { for(int y=0;x;y=x,x=fa[x]) { splay(x); t[t[x].c[1]].fa=0;fa[t[x].c[1]]=x; t[x].c[1]=y;fa[y]=0;t[y].fa=x; } } void link(int x,int y) { access(y);splay(y);fa[x]=y;add(y,t[x].size); } void cut(int x) { access(x);splay(x); add(t[x].c[0],-t[x].size); t[t[x].c[0]].fa=0; fa[t[x].c[0]]=fa[x]; t[x].c[0]=fa[x]=0; }}T;class sam{ public: int insert(int x,int c) { int nx=++cnt;f[nx]=f[x]+1;t[nx].size=1; while(x&&!ch[x][c])ch[x][c]=nx,x=top[x]; if(!x)top[nx]=1,T.link(nx,1); else { int p=ch[x][c]; if(f[p]==f[x]+1)top[nx]=p,T.link(nx,p); else { int np=++cnt;f[np]=f[x]+1; memcpy(ch[np],ch[p],sizeof(ch[p])); top[np]=top[p];T.link(np,top[p]); top[nx]=top[p]=np;T.cut(p); T.link(p,np);T.link(nx,np); while(x&&ch[x][c]==p)ch[x][c]=np,x=top[x]; } } return nx; } int qry(char *s,int len) { int x=1; for(int i=0;i<len;i++) { s[i]-='A'; if(!ch[x][s[i]])return 0; x=ch[x][s[i]]; } T.access(x);T.splay(x); return t[x].size; }}S;void get(int len,int mask){ for(int i=0;i<len;i++) { mask=(mask*131+i)%len; swap(s[i],s[mask]); }}int main(){ int pos=1,sum=0; scanf("%d %s",&Q,s);n=strlen(s); for(int i=0;i<n;i++) pos=S.insert(pos,s[i]-'A'); while(Q--) { scanf(" %s %s",str,s); int len=strlen(s);get(len,mask); if(str[0]=='A') { for(int i=0;i<len;i++) pos=S.insert(pos,s[i]-'A'); } else printf("%d\n",ans=S.qry(s,len)),mask^=ans; } return 0;}
0 0
- Substring
- Substring
- substring
- substring
- Substring
- substring
- substring
- substring
- substring
- substring
- substring
- Substring
- substring
- substring
- substring
- Substring
- substring()
- substring
- 面向切面编程二
- jQuery 向 servlet 发送和接受JSON数据。
- 循环名标签+break、continue控制内外层循环结构
- HI3520D在内核中复用UART2,UART3管脚
- JAVA中常用集合
- SubString
- RxJava操作符(七)Conditional and Boolean
- Android之Loader加载功能
- ActiveMQ 总结(1)
- 分享.NET系统开发过程中积累的扩展方法
- C++第五次实验——数组分离
- vSphere 6.0 部署OVF模板失败,解决方法
- #pragma mark指令的简介和使用
- 常用FFMPEG命令