• bzoj3881 [Coci2015]Divljak


    传送门

    我好菜啊……这种题都不会做……lrd给我讲了之后我才会的……

    不难想到对所有询问串建AC自动机,然后可以在每次加进来一个文本串时维护一下答案,询问的时候直接回答。

    每次扔进来一个文本串的时候fail树上经过的节点到根节点的所有节点的出现次数都会+1,但注意有很多节点会被算重了,这时就需要搞一个树链的并。

    首先把节点按fail树的dfs序排序,每个点的标记+1,相邻两个节点的LCA处标记-1。不难看出来这样刚好可以不重不漏覆盖树链的并的所有点,这样询问时直接子树求和即可。因为需要动态维护区间和,所以要用到树状数组。

      1 /**************************************************************
      2     Problem: 3881
      3     User: _Angel_
      4     Language: C++
      5     Result: Accepted
      6     Time:14220 ms
      7     Memory:506028 kb
      8 ****************************************************************/
      9 #include<cstdio>
     10 #include<cstring>
     11 #include<algorithm>
     12 #include<vector>
     13 using namespace std;
     14 const int maxn=100010,maxm=2000010;
     15 int insert(const char*);
     16 void getfail();
     17 void dfs(int);
     18 void match(const char*);
     19 int LCA(int,int);
     20 void add(int,int);
     21 int query(int);
     22 bool cmp(int,int);
     23 int ch[maxm][26]={{0}},f[maxm][26]={{0}},q[maxm]={0},sum[maxm]={0},cnt=0;
     24 vector<int>G[maxm];
     25 int dfn[maxm],finish[maxm],tim=0,d[maxm]={0},c[maxm]={0},a[maxm];
     26 char s[maxm];
     27 int n,m,lgn=0,iter[maxn],t,x;
     28 int main(){
     29     scanf("%d",&n);
     30     for(int i=1;i<=n;i++){
     31         scanf("%s",s);
     32         iter[i]=insert(s);
     33     }
     34     getfail();
     35     dfs(0);
     36     for(int j=1;j<=lgn;j++)for(int i=1;i<=cnt;i++)f[i][j]=f[f[i][j-1]][j-1];
     37     scanf("%d",&m);
     38     while(m--){
     39         scanf("%d",&t);
     40         if(t==1){
     41             scanf("%s",s);
     42             match(s);
     43         }
     44         else{
     45             scanf("%d",&x);
     46             x=iter[x];
     47             printf("%d
    ",query(finish[x])-query(dfn[x]-1));
     48         }
     49     }
     50     return 0;
     51 }
     52 int insert(const char *c){
     53     int x=0;
     54     while(*c){
     55         if(!ch[x][*c-'a'])ch[x][*c-'a']=++cnt;
     56         x=ch[x][*c++-'a'];
     57     }
     58     return x;
     59 }
     60 void getfail(){
     61     int x,head=0,tail=0;
     62     for(int c=0;c<26;c++)if(ch[0][c])q[tail++]=ch[0][c];
     63     while(head!=tail){
     64         x=q[head++];//printf("x=%d fail=%d
    ",x,f[x][0]);
     65         G[f[x][0]].push_back(x);
     66         fill(f[x]+1,f[x]+26,cnt+1);
     67         for(int c=0;c<26;c++){
     68             if(ch[x][c]){
     69                 int y=f[x][0];
     70                 while(y&&!ch[y][c])y=f[y][0];
     71                 f[ch[x][c]][0]=ch[y][c];
     72                 q[tail++]=ch[x][c];
     73             }
     74             else ch[x][c]=ch[f[x][0]][c];
     75         }
     76     }
     77     fill(f[0],f[0]+26,cnt+1);
     78 }
     79 void dfs(int x){//printf("dfs(%d)
    ",x);
     80     dfn[x]=++tim;
     81     d[x]=d[f[x][0]]+1;
     82     while((1<<lgn)<d[x])lgn++;
     83     for(int i=0;i<(int)G[x].size();i++)dfs(G[x][i]);
     84     finish[x]=tim;
     85 }
     86 void match(const char *c){
     87     int x=0;
     88     a[0]=0;
     89     while(*c){
     90         x=ch[x][*c++-'a'];
     91         a[++a[0]]=x;
     92     }
     93     sort(a+1,a+a[0]+1,cmp);
     94     add(dfn[a[1]],1);
     95     for(int i=2;i<=a[0];i++){
     96         add(dfn[LCA(a[i],a[i-1])],-1);
     97         add(dfn[a[i]],1);
     98     }
     99 }
    100 int LCA(int x,int y){//printf("LCA(%d,%d)=",x,y);
    101     if(d[x]!=d[y]){
    102         if(d[x]<d[y])swap(x,y);
    103         for(int i=lgn;i>=0;i--)if(d[f[x][i]]>=d[y])x=f[x][i];
    104     }
    105     if(x==y)return x;
    106     for(int i=lgn;i>=0;i--)if(f[x][i]!=f[y][i]){
    107         x=f[x][i];
    108         y=f[y][i];
    109     }
    110     return f[x][0];
    111 }
    112 void add(int x,int d){
    113     while(x<=tim){
    114         c[x]+=d;
    115         x+=x&-x;
    116     }
    117 }
    118 int query(int x){
    119     int ans=0;
    120     while(x){
    121         ans+=c[x];
    122         x&=x-1;
    123     }
    124     return ans;
    125 }
    126 bool cmp(int x,int y){return dfn[x]<dfn[y];}
    View Code
  • 相关阅读:
    SQL解发器与SQL游标实例
    动态调用JS
    HDU_5729_rmq+二分
    struts2 在MyEclipse中 的配置
    Struts 1.2 中如何测试Action
    OGNL使用小结【转】
    JUnit中assertEquals和assertSame方法的不同
    struts2 ActionContext
    ser文件与Java对象序列化
    测试Action组件代码(StrutsTestCase)
  • 原文地址:https://www.cnblogs.com/hzoier/p/6550677.html
Copyright © 2020-2023  润新知