• BZOJ 3881 [COCI2015]Divljak (Trie图+Fail树+树链的并+树状数组维护dfs序)


    题目大意:

    Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的。

    接下来会发生q个操作,操作有两种形式:

    “1 P”,Bob往自己的集合里添加了一个字符串P。
    “2 x”,Alice询问Bob,集合T中有多少个字符串包含串S_x。(我们称串A包含串B,当且仅当B是A的子串)
    Bob遇到了困难,需要你的帮助。
     

    最先想歪了,想把$T$里的串建自动机,最后失败了..

    正解是对Alice的字符串建AC自动机,再建$Fail$树

    那么对于操作1,每加入一个字符串,就把这个串放到AC自动机上跑

    再把路径上的所有点记下来,新加入的字符串会对连接这些节点的树链上的所有点产生1点贡献

    即求树链的并,用树状数组维护$dfs$序

    先把这些节点按照$dfs$序排序,然后在树上打差分,树状数组维护前缀和,单点修改

    每个节点都+1,$dfs$序中相邻节点的$lca$-1,最后在全局$lca$的父节点-1

    询问就是子树查询

      1 #include <cmath>
      2 #include <queue>
      3 #include <vector>
      4 #include <cstdio>
      5 #include <cstring>
      6 #include <algorithm>
      7 #define NN 2001000
      8 #define MM 1510
      9 #define ll long long
     10 #define dd double  
     11 #define uint unsigned int
     12 #define mod 1000000007
     13 #define idx(X) (X-'a')
     14 #define eps (1e-9)
     15 using namespace std;
     16 
     17 int n,m,cte;
     18 int head[NN];
     19 struct Edge{int to,nxt;}edge[NN];
     20 void ae(int u,int v){
     21     cte++;edge[cte].nxt=head[u];
     22     head[u]=cte,edge[cte].to=v;
     23 }
     24 struct BIT{
     25 int sum[NN*2],tot;
     26 void update(int x,int w){
     27     for(int i=x;i<=tot;i+=(i&(-i)))
     28         sum[i]+=w;}
     29 int query(int x){
     30     int ans=0;
     31     for(int i=x;i>0;i-=(i&(-i)))
     32         ans+=sum[i];
     33     return ans;}
     34 }b;
     35 namespace AC{
     36 int ch[NN][26],fail[NN],tot,ed[NN],dep[NN];
     37 void Build_Trie(char *str,int len,int id)
     38 {
     39     int x=0;
     40     for(int i=1;i<=len;i++){
     41         if(!ch[x][idx(str[i])])
     42             ch[x][idx(str[i])]=++tot,
     43             dep[tot]=dep[x]+1;
     44         x=ch[x][idx(str[i])];
     45     }ed[id]=x;
     46 }
     47 void Build_Fail()
     48 {
     49     queue<int>q;
     50     for(int i=0;i<26;i++)
     51         if(ch[0][i]) q.push(ch[0][i]);
     52     while(!q.empty())
     53     {
     54         int x=q.front();q.pop();
     55         ae(fail[x],x);
     56         for(int i=0;i<26;i++)
     57         {
     58             if(ch[x][i]){
     59                 fail[ch[x][i]]=ch[fail[x]][i];
     60                 q.push(ch[x][i]);
     61             }else{
     62                 ch[x][i]=ch[fail[x]][i];
     63             }
     64         }
     65     }
     66 }
     67 };
     68 char str[NN];
     69 namespace T{
     70 int son[NN],sz[NN],tp[NN],fa[NN],dep[NN];
     71 int st[NN],ed[NN],tot;
     72 void dfs1(int u,int dad)
     73 {
     74     for(int j=head[u];j;j=edge[j].nxt){
     75         int v=edge[j].to;
     76         if(v==dad) continue;
     77         fa[v]=u;dep[v]=dep[u]+1;
     78         dfs1(v,u);
     79         son[u]=sz[v]>sz[son[u]]?v:son[u];
     80     }sz[u]++;
     81 }
     82 void dfs2(int u)
     83 {
     84     st[u]=++tot;
     85     if(son[u]) tp[son[u]]=tp[u],dfs2(son[u]);
     86     for(int j=head[u];j;j=edge[j].nxt){
     87         int v=edge[j].to;
     88         if(v==fa[u]||v==son[u]) continue;
     89         tp[v]=v,dfs2(v);
     90     }ed[u]=++tot;
     91 }
     92 int LCA(int x,int y)
     93 {
     94     while(tp[x]!=tp[y]){
     95         if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
     96         x=fa[tp[x]];
     97     }return dep[x]<dep[y]?x:y;
     98 }
     99 int stk[NN],num;
    100 int cmp(int x,int y){return st[x]<st[y];}
    101 void update(char *str,int len)
    102 {
    103     int x=0,y,ff,v;
    104     for(int i=1;i<=len;i++){
    105         v=AC::ch[x][idx(str[i])];
    106         if((!v)) break;
    107         x=v;stk[++num]=x;
    108     }
    109     sort(stk+1,stk+num+1,cmp);
    110     x=stk[1];
    111     if(num==1){
    112         b.update(st[x],1);
    113         b.update(st[fa[x]],-1);
    114     }else{
    115         b.update(st[x],1);
    116         for(int i=2;i<=num;i++)
    117         {
    118             y=stk[i];ff=LCA(x,y);
    119             b.update(st[y],1);
    120             b.update(st[ff],-1);
    121             x=stk[i];
    122         }ff=LCA(stk[1],stk[num]);
    123         b.update(st[fa[ff]],-1);
    124     }
    125     while(num) stk[num--]=0;
    126 }
    127 int query(int x)
    128 {return b.query(ed[x])-b.query(st[x]-1);}
    129 void solve()
    130 {
    131     dep[0]=1;dfs1(0,-1);
    132     tp[0]=0;dfs2(0);
    133     scanf("%d",&m);
    134     int fl,x;
    135     b.tot=tot;
    136     for(int i=1;i<=m;i++)
    137     {
    138         scanf("%d",&fl);
    139         if(fl==1){
    140             scanf("%s",str+1);
    141             int len=strlen(str+1);
    142             update(str,len);
    143         }else{
    144             scanf("%d",&x);
    145             printf("%d
    ",query(AC::ed[x]));
    146         }
    147     }
    148 }
    149 };
    150 
    151 
    152 int main()
    153 {
    154     scanf("%d",&n);
    155     for(int i=1;i<=n;i++){
    156         scanf("%s",str+1);
    157         int len=strlen(str+1);
    158         AC::Build_Trie(str,len,i);
    159     }AC::Build_Fail();
    160     T::solve();
    161     return 0;
    162 }
     
     
  • 相关阅读:
    jmeter中生成html测试报告
    jmeter插件管理
    Jmeter参数化
    jmeter测试实例
    jmeter调用时间函数
    Jmeter参数关联
    JMeter的使用流程
    Jmeter 响应结果乱码解决
    使用BadBoy录制JMeter脚本
    jemter安装
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10019940.html
Copyright © 2020-2023  润新知