码迷,mamicode.com
首页 > 其他好文 > 详细

[BZOJ2434]阿狸的打字机

时间:2017-07-02 20:30:35      阅读:355      评论:0      收藏:0      [点我收藏+]

标签:cst   ons   strlen   root   在线   vector   output   键盘   for   

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\n",ans[i]);
114 }
BZOJ2434

[BZOJ2434]阿狸的打字机

标签:cst   ons   strlen   root   在线   vector   output   键盘   for   

原文地址:http://www.cnblogs.com/LadyLex/p/7106936.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!