zoukankan      html  css  js  c++  java
  • BZOJ5084[hashit]

    题解:

    后缀自动机

    我们可以通过建立trie

    把询问变成询问一些点的并

    把trie建立成SAM和广义SAM基本相同,就是在父亲和儿子之间连边

    然后就变成了询问树链的并

    我们可以发现答案=sigma dis[i]  -sigma(dis[lca(i,i+1)])

    其中i和i+1dfs序相邻

    可以通过set来维护

    ***

    把倍增的预处理写在了dfs前

    把&&写成了&

    代码:

    #include <bits/stdc++.h>
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (rint i=h;i<=t;i++)
    #define dep(i,t,h) for (rint i=t;i>=h;i--)
    #define ll long long
    using namespace std;
    const int N=2e5;
    char s[N];
    int len,cnt,son[N][26],pos[N],cnt2;
    struct hz{
      int ch[N][26],node,len[N],fa[N];
      hz()
      {
        node=1; 
      }
      int extend(int c,int z)
      {
      int lst=z;
      int f=lst;
      if (ch[f][c]&&len[ch[f][c]]==len[f]+1)
      { 
        lst=ch[f][c];
        return(lst);
      }
      int p=++node; lst=p;
      len[p]=len[f]+1; //size[p][pl]=1;
      while (f&&!ch[f][c]) ch[f][c]=p,f=fa[f];
      if (!f) { fa[p]=1; return(p);};
      int x=ch[f][c],y=++node;
      if (len[f]+1==len[x]) {fa[p]=x; node--;return(p);}
      len[y]=len[f]+1; fa[y]=fa[x]; fa[x]=fa[p]=y;
      memcpy(ch[y],ch[x],sizeof(ch[x]));
      while (f&&ch[f][c]==x) ch[f][c]=y,f=fa[f];
      return(p);
      }
      void build(int x)
      {
        rep(i,0,25)
          if (son[x][i])
          {
            pos[son[x][i]]=extend(i,pos[x]);
            build(son[x][i]);
          }
      }
    }S;
    int l,head[N],bz[N][21],dfn[N],rl[N],dis[N],fa[N],dep[N],zt[N];
    struct re{
      int a,b;
    }a[N];
    void arr(int x,int y)
    {
      a[++l].a=head[x];
      a[l].b=y;
      head[x]=l;
    }
    void dfs(int x,int y)
    {
      int u=head[x]; bz[x][0]=y; dfn[x]=++cnt2; rl[cnt2]=x;
      dep[x]=dep[y]+1; 
      dis[x]=dis[y]+S.len[x]-S.len[y];
      while (u)
      {
        int v=a[u].b;
        dfs(v,x);
        u=a[u].a;
      }
    }
    set<int> M;
    set<int>::iterator it;
    int lca(int x,int y)
    {
      if (dep[x]<dep[y]) swap(x,y);
      dep(i,20,0)
        if (dep[bz[x][i]]>=dep[y]) x=bz[x][i];
      if (x==y) return(x);
      dep(i,20,0)
        if (bz[x][i]!=bz[y][i]) x=bz[x][i],y=bz[y][i];
      return(bz[x][0]); 
    }
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("3.out","w",stdout);
      scanf("%s",s);
      len=strlen(s);
      int now=1;
      cnt=1;
      rep(i,0,len-1)
      {
        if (s[i]=='-') now=fa[now];
        else
        {
          if (!son[now][s[i]-'a']) son[now][s[i]-'a']=++cnt,fa[cnt]=now;
          now=son[now][s[i]-'a'];
        }
      }
      pos[1]=1; S.build(1);
      for(int i=2;i<=S.node;i++) arr(S.fa[i],i);
      dfs(1,0);
        rep(i,1,20)
        rep(j,1,S.node) bz[j][i]=bz[bz[j][i-1]][i-1];
      ll ans=0; now=1;
     int cnt3=0;
      rep(i,0,len-1)
      {
        if (s[i]=='-')
        {
          int x=0,y=0;
          ans-=dis[now];
          it=M.find(dfn[now]); it++;
          if (it!=M.end()) x=rl[*it]; it--;
          if (it!=M.begin()) y=rl[*--it];
          M.erase(dfn[now]);
          if (x) ans+=dis[lca(now,x)];
          if (y) ans+=dis[lca(now,y)];
          if (x&&y) ans-=dis[lca(x,y)];
          now=zt[--cnt3];
        } else
        {
          int x=0,y=0;
          now=S.ch[now][s[i]-'a'];
          zt[++cnt3]=now;
          ans+=dis[now];
          it=M.insert(dfn[now]).first; 
          it++;
          if (it!=M.end()) x=rl[*it]; it--; 
          if (it!=M.begin())
          { 
            y=rl[*--it];
          }
          if (x) ans-=dis[lca(now,x)];
          if (y) ans-=dis[lca(now,y)];
          if (x&&y) ans+=dis[lca(x,y)];
       //   cout<<lca(pos[now],x)<<" "<<lca(pos[now],y)<<" "<<x<<" "<<y<<endl; 
        }
        printf("%lld
    ",ans);
      }
      return 0;
    }
  • 相关阅读:
    三步完成自适应网页设计
    EasyUI DataGrid 修改每页显示数量的最大值&&导出Grid到Excel
    EasyUI DataGrid 实用例子(2015-05-22)
    C# 如何将List拆分成多个子集合
    EasyUI Tabs绑定右键
    微信支付-扫码支付备忘
    微信支付:模板消息实现过程备忘
    4、http协议之二
    1、套按字及http基础知识之一
    3、Web server 之httpd2.2 配置说明
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9431248.html
Copyright © 2011-2022 走看看