• BZOJ 2780 Sevenk Love Oimaster (后缀自动机+树状数组+dfs序+离线)


    题目大意:

    给你$n$个大串和$m$个询问,每次给出一个字符串$s$询问在多少个大串中出现过

    好神的一道题

    对$n$个大串建出广义$SAM$,建出$parent$树

    把字符串$s$放到$SAM$里跑,找到能表示字符串$s$的节点$x$

    问题转化为在$parent$树中,$x$节点的子树内,有多少个编号不同的$endpos$节点

    把树拍扁,转化为$dfs$序

    不就是在序列上跑HH的项链么,离线树状数组维护一下就好

    一个节点可能有多个不同串$endpos$标记,用$vector$存一下串的编号就行了

    注意索引不要写错,不要把数组开小了

      1 #include <vector>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define N1 105000
      6 #define S1 (N1<<1)
      7 #define T1 (N1<<2)
      8 #define ll long long
      9 #define uint unsigned int
     10 #define rint register int 
     11 #define il inline 
     12 #define inf 0x3f3f3f3f
     13 #define idx(X) (X-'a')
     14 using namespace std;
     15 
     16 int gint()
     17 {
     18     int ret=0,fh=1;char c=getchar();
     19     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     20     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
     21     return ret*fh;
     22 }
     23 
     24 int n,m,len,tot;
     25 char str[N1];
     26 struct Edge{
     27 int to[T1],nxt[T1],head[T1],cte;
     28 void ae(int u,int v){
     29     cte++;to[cte]=v;nxt[cte]=head[u],head[u]=cte;}
     30 }E,Q;
     31 struct BIT{
     32 int sum[T1],ma;
     33 void upd(int x,int w){
     34     for(int i=x;i<=ma;i+=(i&(-i)))
     35         sum[i]+=w;}
     36 int query(int x){
     37     int ans=0;
     38     for(int i=x;i>0;i-=(i&(-i)))
     39         ans+=sum[i];
     40     return ans;}
     41 }b;
     42 namespace SAM{
     43 int trs[S1][26],pre[S1],dep[S1],la;
     44 vector<int>ed[S1];
     45 void init(){tot=la=1;}
     46 void reduct(){la=1;}
     47 void insert(int x,int id)
     48 {
     49     int p=la,q,np=++tot,nq;la=np;
     50     dep[np]=dep[p]+1;
     51     ed[np].push_back(id);
     52     for(;p&&!trs[p][x];p=pre[p]) trs[p][x]=np;
     53     if(!p) pre[np]=1;
     54     else{
     55         q=trs[p][x];
     56         if(dep[q]==dep[p]+1) pre[np]=q;
     57         else{
     58             pre[nq=++tot]=pre[q];
     59             pre[q]=pre[np]=nq;
     60             dep[nq]=dep[p]+1;
     61             memcpy(trs[nq],trs[q],sizeof(trs[q]));
     62             for(;p&&trs[p][x]==q;p=pre[p]) trs[p][x]=nq;
     63         }
     64     }
     65 }
     66 void Build_Edge()
     67 {
     68     for(int i=2;i<=tot;i++)
     69         E.ae(pre[i],i);
     70 }
     71 int find(char *str,int L)
     72 {
     73     int x=1;
     74     for(int i=1;i<=L;i++){
     75         x=trs[x][idx(str[i])];
     76         if(!x) return 0;
     77     }return x;
     78 }
     79 };
     80 namespace Seq{
     81 int st[T1],ed[T1],to[T1],ans[T1],la[T1],cnt;
     82 void dfs1(int x)
     83 {
     84     st[x]=++cnt;
     85     for(int j=E.head[x];j;j=E.nxt[j])
     86         dfs1(E.to[j]);
     87     ed[x]=++cnt;
     88     to[cnt]=x;
     89 }
     90 void solve()
     91 {
     92     dfs1(1);
     93     b.ma=cnt;
     94     int x,v;
     95     for(int i=1;i<=m;i++)
     96     {
     97         scanf("%s",str+1);
     98         len=strlen(str+1);
     99         x=SAM::find(str,len);
    100         if(x) Q.ae(ed[x],i);
    101     }
    102     for(int i=1;i<=cnt;i++)
    103     {
    104         x=to[i];
    105         for(int j=0;j<SAM::ed[x].size();j++)
    106         {
    107             v=SAM::ed[x][j];
    108             if(!la[v]) b.upd(i,1),la[v]=i;
    109             else b.upd(la[v],-1),la[v]=i,b.upd(i,1);
    110         }
    111         for(int j=Q.head[i];j;j=Q.nxt[j])
    112         {
    113             v=Q.to[j];
    114             ans[v]=b.query(ed[x])-b.query(st[x]);
    115         }
    116     }
    117     for(int i=1;i<=m;i++)
    118         printf("%d
    ",ans[i]);
    119 }
    120 
    121 };
    122 
    123 int main()
    124 {
    125     //freopen("t2.in","r",stdin);
    126     scanf("%d%d",&n,&m);
    127     SAM::init();
    128     for(int i=1;i<=n;i++)
    129     {
    130         scanf("%s",str+1);
    131         len=strlen(str+1);
    132         for(int j=1;j<=len;j++)
    133             SAM::insert(idx(str[j]),i);
    134         SAM::reduct();
    135     }
    136     SAM::Build_Edge();
    137     Seq::solve();
    138     return 0;
    139 }
  • 相关阅读:
    两种选择排序法
    三种方法求组合偶数字
    sizeof和mallo
    多态的概念与接口重用
    Delphi Exception的理解
    给老婆留着
    Delphi 一个简单的DELPHI自定义事件的例子
    Delphi 纯Pascal编写的程序,没有通过VCL
    Delphi 继承类的构造函数和析构函数的构建顺序
    Delphi 对象间数据的复制
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10098149.html
Copyright © 2020-2023  润新知