SubString

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 3000010
using 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;
}

你可能感兴趣的:(SubString)