zoukankan      html  css  js  c++  java
  • BZOJ2434 NOI2011阿狸的打字机

    询问x这个串在y中出现的次数。

    fail数组有一个性质就是一旦a的fail指向b那么b所代表的字串一定是a的后缀。

    所以我们看fail树(即按fail反向建树)中x的子树有多少y的结点即可。

    这个操作可以使用树状数组维护dfs序操作。

    By:大奕哥

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int N=1e5+10;
      4 int head[N],dead[N],cnt,ent,dnt,num,n,m,idx,fa[N],pos[N],l[N],r[N];
      5 char s[N];
      6 queue<int>q;
      7 struct poin{
      8     int v[26],f,s;
      9 }t[N<<1];
     10 struct node{
     11     int to,nex;
     12 }e[N];
     13 struct edge{
     14     int to,nex;
     15 }d[N];
     16 void add(int x,int y)
     17 {
     18     e[++ent].to=y;e[ent].nex=head[x];head[x]=ent;
     19 }
     20 void add2(int x,int y)
     21 {
     22     d[++dnt].to=y;d[dnt].nex=dead[x];dead[x]=dnt;
     23 }
     24 int tr[N<<1];
     25 inline int lowbit(int x){return x&(-x);}
     26 int query(int x)
     27 {
     28     int ans=0;
     29     for(;x;x-=lowbit(x))ans+=tr[x];
     30     return ans;
     31 }
     32 void update(int x,int w)
     33 {
     34     for(;x<=idx;x+=lowbit(x))tr[x]+=w;
     35 }
     36 void build()
     37 {
     38     int now=0;
     39     for(int i=0;i<n;++i)
     40     {
     41         if(s[i]=='P')pos[++num]=now;
     42         else if(s[i]=='B')now=fa[now];
     43         else{
     44             if(!t[now].v[s[i]-'a'])
     45                 t[now].v[s[i]-'a']=++cnt;
     46             fa[t[now].v[s[i]-'a']]=now;
     47             now=t[now].v[s[i]-'a'];
     48         }
     49     }
     50     return;
     51 }
     52 void getfail()
     53 {
     54     for(int i=0;i<26;++i)
     55     {
     56         if(t[0].v[i])
     57         q.push(t[0].v[i]),t[t[0].v[i]].f=0;
     58     }
     59     while(!q.empty())
     60     {
     61         int x=q.front();q.pop();
     62         for(int i=0;i<26;++i)
     63         {
     64             if(t[x].v[i])
     65             {
     66                 t[t[x].v[i]].f=t[t[x].f].v[i];
     67                 q.push(t[x].v[i]);
     68             }
     69             else{
     70                 t[x].v[i]=t[t[x].f].v[i];
     71             }
     72         }
     73     }
     74     return;
     75 }
     76 void maketree()
     77 {
     78     for(int i=1;i<=cnt;++i)
     79     {
     80         int x=t[i].f;int y=i;
     81         add(x,y);
     82     }
     83     return;
     84 }
     85 void dfs(int x)
     86 {
     87     l[x]=++idx;
     88     for(int i=head[x];i;i=e[i].nex)
     89     {
     90         int y=e[i].to;
     91         dfs(y);
     92     }
     93     r[x]=++idx;
     94     return;
     95 }
     96 int ans[N];
     97 void work()
     98 {
     99     scanf("%d",&m);int id;int x,y;
    100     for(int i=1;i<=m;++i)
    101     {
    102         scanf("%d%d",&x,&y);add2(y,x);
    103     }int now=0;
    104     for(int i=0;i<n;++i)
    105     {
    106         if(s[i]=='B')
    107         {
    108             update(l[now],-1);now=fa[now];
    109         }
    110         else if(s[i]=='P')
    111         {
    112             ++id;
    113             for(int j=dead[id];j;j=d[j].nex)
    114             {
    115                 int y=pos[d[j].to];
    116                 ans[j]=query(r[y])-query(l[y]-1);
    117             }
    118         }
    119         else
    120         {
    121             now=t[now].v[s[i]-'a'];
    122             update(l[now],1);
    123         }
    124     }
    125     for(int i=1;i<=m;++i)
    126     printf("%d
    ",ans[i]);
    127     return;
    128 }
    129 int main()
    130 {
    131     scanf("%s",s);
    132     n=strlen(s);
    133     build();
    134     getfail();
    135     maketree();
    136     dfs(0);
    137     work();
    138     return 0;
    139 }
  • 相关阅读:
    通知协议KVO的用法
    UIImageView用法
    默默的学习!
    多输入参数的方法
    一本书的摘录
    实例、局部、静态变量(java)
    分数相加的例题
    类的继承
    多线程
    单例
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8328874.html
Copyright © 2011-2022 走看看