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