• luogu P2336 [SCOI2012]喵星球上的点名


    传送门

    这题tm把AC自动机叉掉了,,,

    只能考虑别的做法

    把所有串连在一起,不同串的交界处加入一些不同的字符,然后求出sa数组和height数组,现在一个询问的答案就是和那个询问串的lcp正好为询问串长度的原串个数,而这在把后缀排好序后是一个区间,每个原串答案为包含这个原串的某个点的区间个数

    如果将每个原串的点染成对应编号的颜色,那么现在求的是每个区间包含的点的颜色种类和每种点被多少个区间包含,可以用莫队实现,前者就是HH的项链,后者可以在每种颜色对第一种答案加上贡献时对其答案加上剩余询问个数,在对第一种答案减去贡献时对其答案减去剩余询问个数

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define LL long long
    #define il inline
    #define re register
    #define db double
    
    using namespace std;
    const int N=400000+10,M=100000+10;
    il int rd()
    {
      int x=0,w=1;char ch=0;
      while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
      while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
      return x*w;
    }
    int n,l1,l2,m=10000;
    int rk[N],sa[N],wr[N],bk[N],wx[N],he[N];
    int cc[N];
    il bool cmp(int a,int b,int j){return wr[a]==wr[b]&&wr[a+j]==wr[b+j];}
    il void gSA(int m)
    {
      for(int i=1;i<=n;++i) ++bk[rk[i]=cc[i]];
      for(int i=1;i<=m;++i) bk[i]+=bk[i-1];
      for(int i=n;i;--i) sa[bk[rk[i]]--]=i;
      int tp,j=1,p=0;
      while(p<n)
        {
          tp=0;
          for(int i=n-j+1;i<=n;++i) wx[++tp]=i;
          for(int i=1;i<=n;++i) if(sa[i]>j) wx[++tp]=sa[i]-j;
          for(int i=1;i<=n;++i) wr[i]=rk[wx[i]];
          for(int i=0;i<=m;++i) bk[i]=0;
          for(int i=1;i<=n;++i) ++bk[wr[i]];
          for(int i=1;i<=m;++i) bk[i]+=bk[i-1];
          for(int i=n;i;--i) sa[bk[wr[i]]--]=wx[i];
          for(int i=1;i<=n;++i) wr[i]=rk[i];
          rk[sa[1]]=p=1;
          for(int i=2;i<=n;++i) rk[sa[i]]=p+=(cmp(sa[i],sa[i-1],j)^1);
          m=p,j<<=1;
        }
      for(int i=1,j;i<=n;++i)
        {
          he[rk[i]]=he[rk[i-1]]?he[rk[i-1]]-1:0;
          j=sa[rk[i]-1];
          while(cc[i+he[rk[i]]]==cc[j+he[rk[i]]]) ++he[rk[i]];
        }
    }
    int p[M][2],w[M],len[M],be[N],b2[N],cn[M],na,a1[M],a2[M];
    il void ad(int x,int res)
    {
      ++cn[b2[sa[x]]];
      if(b2[sa[x]]&&cn[b2[sa[x]]]==1) ++na,a2[b2[sa[x]]]+=res;
    }
    il void dl(int x,int res)
    {
      --cn[b2[sa[x]]];
      if(b2[sa[x]]&&cn[b2[sa[x]]]==0) --na,a2[b2[sa[x]]]-=res;
    }
    int mi[N][20],hbt[N];
    il int gmin(int l,int r)
    {
      if(l>r) swap(l,r);
      ++l;
      if(l>r) return -1;
      int z=hbt[r-l+1];
      return min(mi[l][z],mi[r-(1<<z)+1][z]);
    }
    struct qu
    {
      int l,r,id;
      bool operator < (const qu bb) const {return (be[l]^be[bb.l])?l<bb.l:r<bb.r;}
    }qq[M];
    
    int main()
    {
      l1=rd(),l2=rd();
      cc[0]=m;
      for(int i=1;i<=l1;++i)
        {
          p[i][0]=n+1;
          int k=rd();
          while(k--) cc[++n]=rd();
          cc[++n]=++m;
          k=rd();
          while(k--) cc[++n]=rd();
          cc[++n]=++m;
          p[i][1]=n-1;
        }
      for(int i=1;i<=l2;++i)
        {
          w[i]=n+1;
          int k=len[i]=rd();
          while(k--) cc[++n]=rd();
          cc[++n]=++m;
        }
      --n;
      gSA(m);
      int sqrtn=sqrt(n),lz=log2(n);
      hbt[0]=-1;
      for(int i=0;i<=n;++i) be[i]=i/sqrtn;
      for(int i=1;i<=n;++i) hbt[i]=hbt[i-1]+((i&(-i))==i);
      for(int i=1;i<=n;++i)
        mi[i][0]=he[i];
      for(int j=1;j<=lz;++j)
        for(int i=1;i<=n-(1<<(j-1));++i)
          mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]);
      for(int i=1;i<=l2;++i)
        {
          qq[i].l=qq[i].r=rk[w[i]],qq[i].id=i;
          int l=1,r=rk[w[i]]-1;
          while(l<=r)
            {
              int mid=(l+r)>>1;
              if(gmin(mid,rk[w[i]])==len[i]) qq[i].l=mid,r=mid-1;
              else l=mid+1;
            }
          l=rk[w[i]]+1,r=n;
          while(l<=r)
            {
              int mid=(l+r)>>1;
              if(gmin(rk[w[i]],mid)==len[i]) qq[i].r=mid,l=mid+1;
              else r=mid-1;
            }
        }
      sort(qq+1,qq+l2+1);
      for(int i=1,j=1;;++i)
        {
          while(j<=l1&&i>p[j][1]) ++j;
          if(j>l1) break;
          b2[i]=(i>=p[j][0]?j:0);
        }
      for(int i=1,l=1,r=0;i<=l2;++i)
        {
          while(r<qq[i].r) ++r,ad(r,l2-i+1);
          while(r>qq[i].r) dl(r,l2-i+1),--r;
          while(l<qq[i].l) dl(l,l2-i+1),++l;
          while(l>qq[i].l) --l,ad(l,l2-i+1);
          a1[qq[i].id]=na;
        }
      for(int i=1;i<=l2;++i) printf("%d
    ",a1[i]);
      for(int i=1;i<=l1;++i) printf("%d ",a2[i]);
      return 0;
    }
    

    推荐去dd我的xzz巨佬博客看更优秀的题解

  • 相关阅读:
    [osg][原]自定义osgGA漫游器
    [osg]osg窗口显示和单屏幕显示
    sql中去除重复的数据 select distinct * from table
    Microsoft VBScript 运行时错误 错误 800a005e 无效使用 Null: Replace
    如何解决Access操作或事件已被禁用模式阻止
    sql 中 '' 与 null 的区别
    IsNull、rs、sum
    Access与SQL中的IsNull(),IS NULL的区别
    ASP将Table导出Excel
    ASP如何将table导出EXCEL表格
  • 原文地址:https://www.cnblogs.com/smyjr/p/10100311.html
Copyright © 2020-2023  润新知