bzoj 3881 [Coci2015]Divljak——LCT维护parent树链并

Posted narh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 3881 [Coci2015]Divljak——LCT维护parent树链并相关的知识,希望对你有一定的参考价值。

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3881

对 S 建 SAM ,每个 T 会让 S 的 parent 树的链并答案+1;在 T 走每一步的时候,走到的节点用 LCT access 一下,就能找到该点到 parent 根的链。

给链打标记。在 access 的过程中,如果遇到已经打过这个 T 标记的点,就停止 access 。

注意实现的时候,在判断 fa[x] 有没有标记之前要先 splay(fa[x]) 。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ls c[cr][0]
#define rs c[cr][1]
using namespace std;
int rdn()
{
  int ret=0;bool fx=1;char ch=getchar();
  while(ch>9||ch<0){if(ch==-)fx=0;ch=getchar();}
  while(ch>=0&&ch<=9)ret=ret*10+ch-0,ch=getchar();
  return fx?ret:-ret;
}
const int N=1e5+5,M=2e6+5,K=26;
int n,ps[N],tot=1,c[M][K],tc[M][K],fl[M],q[M];
int tim,dfn[M],fa[M],vl[M],tg[M],sta[M];
char s[M];
bool isrt(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
void cz(int cr)
{
  if(!tg[cr])return; int w=tg[cr];tg[cr]=0;
  vl[ls]+=w; vl[rs]+=w;
  tg[ls]+=w; tg[rs]+=w;
  dfn[ls]=dfn[rs]=dfn[cr];///
}
void rotate(int x)
{
  int y=fa[x],z=fa[y],d=(x==c[y][1]);
  if(!isrt(y))c[z][y==c[z][1]]=x;
  fa[x]=z; fa[y]=x; fa[c[x][!d]]=y;
  c[y][d]=c[x][!d]; c[x][!d]=y;
}
void splay(int x)
{
  int top; sta[top=1]=x;
  for(int k=x;!isrt(k);k=fa[k])sta[++top]=fa[k];
  for(int i=top;i;i--)cz(sta[i]);
  for(int y=fa[x],z=fa[y];!isrt(x);rotate(x),y=fa[x],z=fa[y])
    if(!isrt(y))
      ((y==c[z][0])^(x==c[y][0]))?rotate(x):rotate(y);
}
void access(int x)
{
  splay(x); if(dfn[x]==tim)return;
  int t=0;
  while(1)
    {
      c[x][1]=t;
      if(!fa[x])
    { tg[x]++;vl[x]++;dfn[x]=tim;return;}
      splay(fa[x]);//splay first
      if(dfn[fa[x]]==tim)
    { tg[x]++;vl[x]++;dfn[x]=tim;return;}
      t=x; x=fa[x];
    }
}
void link(int x,int y){ fa[y]=x;}
int Ins()
{
  int cr=1,len=strlen(s+1);
  for(int i=1;i<=len;i++)
    {
      int w=s[i]-a;
      if(!tc[cr][w])tc[cr][w]=++tot;
      cr=tc[cr][w];
    }
  return cr;
}
void get_fl()
{
  int he=0,tl=0;
  for(int i=0,v;i<K;i++)
    if((v=tc[1][i]))
      {q[++tl]=v;fl[v]=1;link(1,v);}
    else tc[1][i]=1;
  while(he<tl)
    {
      int k=q[++he],pr=fl[k];
      for(int i=0,v;i<K;i++)
    if((v=tc[k][i]))
      { q[++tl]=v;fl[v]=tc[pr][i];link(tc[pr][i],v);}
    else tc[k][i]=tc[pr][i];
    }
}
void solve()
{
  tim++; int cr=1,len=strlen(s+1);
  for(int i=1;i<=len;i++)
    {
      cr=tc[cr][s[i]-a];
      access(cr);
    }
}
int main()
{
  n=rdn();
  for(int i=1;i<=n;i++)
    { scanf("%s",s+1); ps[i]=Ins();}
  get_fl();
  int Q=rdn(),op,x;
  while(Q--)
    {
      op=rdn();
      if(op==1)
    { scanf("%s",s+1); solve();}
      else
    {
      x=rdn(); x=ps[x];
      splay(x); printf("%d\n",vl[x]);
    }
    }
  return 0;
}

 

以上是关于bzoj 3881 [Coci2015]Divljak——LCT维护parent树链并的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 3881 [Coci2015]Divljak——LCT维护parent树链并

BZOJ3881 Coci2015 Divljak fail树+差分

bzoj3881[Coci2015]Divljak AC自动机+树链的并+DFS序+树状数组

[BZOJ3745][COCI2015]Norma(分治)

BZOJ3745[Coci2015]Norma cdq分治

BZOJ3743[Coci2015]Kamp 树形DP