• [NOI 2011][BZOJ 2434] 阿狸的打字机


    传送门

    AC自动机 + 树状数组

    建成AC自动机后,设end[i]为第i个串的末尾在Trie树上的节点。

    可以发现,对于一个询问(x,y),ans等于Trie树上root到end[y]这条链上fail指针指向end[x]的节点数,我们把这些点记为特殊点

    因为Trie树上每个节点fail指针仅指向一个值,

    因此可以将fail指针反转构建一棵树,以下称为fail树。

    于此答案可以等价于在fail树上以end[x]为根的子树中存在的特殊点个数。

    然而这样暴力做还是过不了。于是需要一些优化。

    可以知道将一个树的节点按dfs序排列后,

    树的任意一颗子树的节点在序列中都是连续的一段区间。

    我们把特殊的点记为1,非特殊点记为0,

    于是求某子树上的特殊点个数可以转化成求某区间的和,

    于是就可以用树状数组来优化了。(线段树应该也可以吧,不过似乎会比较麻烦)。

    代码:

      1 #include<cstdio>
      2 #include<queue>
      3 #include<algorithm>
      4 #include<cstring>
      5 
      6 using namespace std;
      7 
      8 #define N ((1<<17)-1)
      9 #define M ((1<<17)-1)
     10 #define lowbit(x) ((x)&(-(x)))
     11 
     12 queue<int>q;
     13 char s[N];
     14 int end[N],n;
     15 
     16 struct ACA
     17 {
     18     int cnt;
     19     int fa[N],son[N][26],fail[N];
     20     void get_trie()
     21     {
     22         cnt=1;
     23         int i,now=1,v,p=0;
     24         for (i=0;i<n;i++)
     25             switch(s[i])
     26             {
     27                 case 'P':{end[++p]=now;break;}
     28                 case 'B':{now=fa[now];break;}
     29                 default:
     30                 {
     31                     v=s[i]-'a';
     32                     if (!son[now][v])
     33                     {
     34                         son[now][v]=++cnt;
     35                         fa[cnt]=now;    
     36                     }
     37                     now=son[now][v];
     38                 }
     39             }
     40         for (i=0;i<26;i++) son[0][i]=1; 
     41     }
     42     void get_fail()
     43     {
     44         int i,j,x;
     45         q.push(1);
     46         while (!q.empty())
     47         {
     48             x=q.front(),q.pop();
     49             for (i=0;i<26;i++)
     50                 if (son[x][i])
     51                 {
     52                     for (j=fail[x];j&&!son[j][i];j=fail[j]);
     53                     fail[son[x][i]]=son[j][i];
     54                     q.push(son[x][i]);
     55                 }
     56         }
     57     }
     58 }aca;
     59 
     60 struct BIT
     61 {
     62     int arr[N],l[N],r[N];
     63     int sum(int i)
     64     {
     65         int re=0;
     66         while (i)
     67         {re+=arr[i];i-=lowbit(i);}
     68         return re;
     69     }
     70     void add(int i,int k)
     71     {
     72         while (i<=aca.cnt)
     73         {arr[i]+=k;i+=lowbit(i);}    
     74     }
     75 }bit;
     76 
     77 
     78 struct Tree
     79 {
     80     vector<vector<int> >son;
     81     void addedge(int u,int v)
     82     {
     83         son[u].push_back(v);
     84     }
     85     void build()
     86     {
     87         son.resize(aca.cnt+1);
     88         for (int i=2;i<=aca.cnt;i++)
     89         addedge(aca.fail[i],i);
     90     }
     91     void dfs_order(int x,int &k)
     92     {
     93         bit.l[x]=bit.r[x]=k++;
     94         for (int i=0;i<son[x].size();i++)
     95         {
     96             dfs_order(son[x][i],k);
     97             bit.r[x]=max(bit.r[x],bit.r[son[x][i]]);
     98         }
     99     }
    100 }tree;
    101 
    102 int x[M],ans[M],pre[N],now[N];
    103 
    104 inline int val(int x)
    105 {
    106     return bit.sum(bit.r[x])-bit.sum(bit.l[x]-1);
    107 }
    108 
    109 void answer()
    110 {
    111     int m,i,j,y,v,p;
    112     scanf("%d",&m);
    113     memset(now,0,sizeof(now));
    114     for (i=1;i<=m;i++)
    115     {
    116         scanf("%d%d",&x[i],&y);
    117         x[i]=end[x[i]];
    118         y=end[y];
    119         pre[i]=now[y];
    120         now[y]=i;
    121     }
    122     for (p=1,i=0;i<n;i++)
    123     {
    124         switch(s[i])
    125         {
    126             case 'P':
    127             {
    128                 for (j=now[p];j;j=pre[j])
    129                     ans[j]=val(x[j]);
    130                 break;
    131             }
    132             case 'B':
    133             {
    134                 bit.add(bit.l[p],-1);
    135                 p=aca.fa[p];
    136                 break;
    137             }
    138             default:
    139             {
    140                 v=s[i]-'a';
    141                 p=aca.son[p][v];
    142                 bit.add(bit.l[p],1);
    143             }
    144         }
    145     }
    146     for (i=1;i<=m;i++)
    147         printf("%d
    ",ans[i]);
    148 }
    149 
    150 int main()
    151 {
    152     scanf("%s",s);
    153     n=strlen(s);
    154     aca.get_trie();
    155     aca.get_fail();
    156     tree.build();
    157     int k=1;
    158     tree.dfs_order(1,k);
    159     answer();
    160 }
    View Code
  • 相关阅读:
    使用 CSS 强制内容不换行
    奇怪的 Object reference not set to an instance of an object
    (String) 和 String.valueOf() 两种字符串转换的区别
    SQL 里面的 UNION 说明
    Flex/AIR 中 Embed 标签的使用
    把 doc、xls、pdf 转换为 swf 的相关工具
    把指定的站点加到 IE 可信站点中
    在 VS 中快速打开文件或类型
    linux配置网卡
    linux配置本地源
  • 原文地址:https://www.cnblogs.com/KaNNeXFF/p/5414550.html
Copyright © 2020-2023  润新知