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

    2434: [Noi2011]阿狸的打字机

    Time Limit: 10 Sec  Memory Limit: 256 MB

    Description

     阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有28个按键,分别印有26个小写英文字母和'B'、'P'两个字母。
    经阿狸研究发现,这个打字机是这样工作的:
    l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。
    l 按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。
    l 按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。
    例如,阿狸输入aPaPBbP,纸上被打印的字符如下:
    a
    aa
    ab
    我们把纸上打印出来的字符串从1开始顺序编号,一直到n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(其中1≤x,y≤n),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。
    阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?

    Input

     输入的第一行包含一个字符串,按阿狸的输入顺序给出所有阿狸输入的字符。
    第二行包含一个整数m,表示询问个数。
    接下来m行描述所有由小键盘输入的询问。其中第i行包含两个整数x, y,表示第i个询问为(x, y)。

    Output

     输出m行,其中第i行包含一个整数,表示第i个询问的答案。

    Sample Input

    aPaPBbP

    3
    1 2
    1 3
    2 3

    Sample Output

    2
    1
    0

    HINT

    1<=N,M<=10^5

    输入总长<=10^5
     
    题解:
    之前听liu_runda学长讲过一遍……
    建树时B,P两个操作很容易处理
    我们考虑,对于两个字符串s[x],s[y],
    x在y中出现的次数,等于y到root的trie路径中,在x的fail树子树中的节点个数
    (其实很好理解,如果某个节点在x的fail树里,那么以这个节点结束的子串里至少有一个x串)
    但是,如果我们每次都在线一个一个查询,会T(比如用倍增,复杂度O(M*len*log(len)))
    那么我们可以离线,记录dfs序并且用树状数组统计节点数,复杂度
    于是这道题就被我们A掉了,代码见下:
      1 #include<cstdio>
      2 #include<cstring>
      3 #include<string>
      4 #include<vector>
      5 using namespace std;
      6 const int L=100000;
      7 int m,num,cnt,cnt_type,hd=1,tl;char text[L+100];
      8 int e,adj[L+100],bit[L+100],ans[L+100];
      9 inline int lowbit(int a){return a&-a;}
     10 inline void add(int pos,int val)
     11 {
     12     while(pos<=cnt)
     13         bit[pos]+=val,pos+=lowbit(pos);
     14 }
     15 inline int sum(int pos)
     16 {
     17     int ret=0;
     18     while(pos)
     19         ret+=bit[pos],pos-=lowbit(pos);
     20     return ret;
     21 }
     22 struct node
     23 {
     24     node *f,*fa,*ch[26];
     25     int id,dfn_l,dfn_r,mark;
     26     node(int v,node *o)
     27     {
     28         memset(ch,0,sizeof(ch));
     29         id=v,mark=0;fa=o,f=NULL;
     30     }
     31 }*root=new node(0,NULL),*q[L+100],*print[L+100];
     32 struct edge{node *qi,*zhong;int next;}s[L+100];
     33 inline void get_fail()
     34 {
     35     q[++tl]=root;
     36     while(hd<=tl)
     37     {
     38         node *rt=q[hd++];
     39         for(int i=0;i<26;i++)
     40         {
     41             if(rt->ch[i])
     42             {
     43                 q[++tl]=rt->ch[i];
     44                 node *u=rt->f;
     45                 while(u&&!u->ch[i])u=u->f;
     46                 rt->ch[i]->f=(u)?u->ch[i]:root;
     47             }
     48         }
     49     }
     50 }
     51 inline void add(node *qi,node *zhong)
     52 {
     53     s[++e].qi=qi;s[e].zhong=zhong;
     54     s[e].next=adj[qi->id],adj[qi->id]=e;
     55 }
     56 inline void build_fail(node *rt)
     57 {
     58     for(int i=0;i<26;i++)
     59         if(rt->ch[i]!=NULL)
     60             add(rt->ch[i]->f,rt->ch[i]),build_fail(rt->ch[i]);
     61 }
     62 void dfs(node *rt)
     63 {
     64     rt->dfn_l=++cnt;
     65     for(int i=adj[rt->id];i;i=s[i].next)
     66         if(s[i].zhong!=NULL)
     67             dfs(s[i].zhong);
     68     rt->dfn_r=cnt;
     69 }
     70 struct Quest{int id;node *pos;};
     71 vector<Quest>quest[L+100];
     72 void work(node *rt)
     73 {
     74     add(rt->dfn_l,1);
     75     for(int i=0;i<quest[rt->id].size();i++)
     76     {
     77         Quest t=quest[rt->id][i];
     78         ans[t.id]=sum(t.pos->dfn_r)-sum(t.pos->dfn_l-1);
     79     }
     80     for(int i=0;i<26;i++)
     81         if(rt->ch[i]!=NULL)
     82             work(rt->ch[i]);
     83     add(rt->dfn_l,-1);
     84 }
     85 int main()
     86 {
     87     scanf("%s",text);int sea=strlen(text);
     88     node *now=root;
     89     for(int i=0;i<sea;i++)
     90     {
     91         if(text[i]=='P')
     92         {
     93             now->mark=++cnt_type;
     94             print[cnt_type]=now;
     95         }
     96         else if(text[i]=='B')
     97                 now=now->fa;
     98             else
     99             {
    100                 if(!now->ch[text[i]-'a'])
    101                     now->ch[text[i]-'a']=new node(++num,now);
    102                 now=now->ch[text[i]-'a'];
    103             }
    104     }
    105     get_fail();build_fail(root);dfs(root);
    106     scanf("%d",&m);int x,y;
    107     for(int i=1;i<=m;i++)
    108     {
    109         scanf("%d%d",&x,&y);
    110         quest[print[y]->id].push_back((Quest){i,print[x]});
    111     }
    112     work(root);
    113     for(int i=1;i<=m;i++)printf("%d
    ",ans[i]);
    114 }
    BZOJ2434
  • 相关阅读:
    CocoStudio基础教程(4)骨骼动画的动态换肤
    CocoStudio基础教程(3)在程序中处理cocoStudio导出动画
    CocoStudio基础教程(2)关联程序逻辑与cocoStudio导出文件
    CocoStudio基础教程(1)创建UI并载入到程序中
    LeetCode:盛最多水的容器【11】
    LeetCode:反转字符串中的元音字母【345】
    LeetCode:验证回文串【125】
    LeetCode:颜色分类【75】
    LeetCode:删除排序数组中的重复项||【80】
    LeetCode:移动零【283】
  • 原文地址:https://www.cnblogs.com/LadyLex/p/7106936.html
Copyright © 2011-2022 走看看