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

    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<=10^5


    1<=M<=10^5

    输入总长<=10^5
     
    这道题看上去很迷啊。。。
    考虑各种字符串做法,这是多模匹配,那就AC机树上硬搞
    想想AC机fail指针定义:是根节点到该节点组成字符串的后缀
    考虑从y串往上跳,构造出一颗后缀树,发现:
    答案是x子树中有多少个y串中的节点,这可以用树状数组优化
    那么就一个一个y串搞,排序下,然后再访问一下给出的打字顺序即可
    代码如下:
    //MT_LI
    #include<cmath> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; struct AC_machine { int son[31],fail,fa; AC_machine(){fail=0;memset(son,-1,sizeof(son));} }t[210000]; int cnt,root,s[210000]; int list[210000]; int l[210000],r[210000],id; int cc[210000]; int lowbit(int x){return x&-x;} void change(int x,int d){while(x<=id)cc[x]+=d,x+=lowbit(x);} int getsum(int x){int sum=0;while(x)sum+=cc[x],x-=lowbit(x);return sum;} int n;char st[210000]; struct node{ int x,y,next; }a[210000];int len,last[210000]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } void init() { scanf("%s",st+1);int slen=strlen(st+1); root=0;cnt=0;n=0;int now=root; for(int i=1;i<=slen;i++) { if(st[i]=='B')now=t[now].fa; else if(st[i]=='P')s[++n]=now; else { int y=st[i]-'a'+1; if(t[now].son[y]==-1)t[now].son[y]=++cnt,t[t[now].son[y]].fa=now; now=t[now].son[y]; } } } void dfs(int x) { l[x]=++id; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; dfs(y); } r[x]=id; } void bfs() { int head=1,tail=2; list[1]=0; while(head!=tail) { int x=list[head]; for(int i=1;i<=26;i++) { int y=t[x].son[i]; if(y!=-1) { if(x==root)t[y].fail=0; else { int p=t[x].fail; while(p!=root&&t[p].son[i]==-1)p=t[p].fail; t[y].fail=t[p].son[i]; } list[tail++]=y; } } head++; } len=0;memset(last,0,sizeof(last)); for(int i=1;i<=cnt;i++)ins(t[i].fail,i); id=0;dfs(root); } struct Q{ int x,y,id; }q[210000]; bool cmp(Q a,Q b){return a.y<b.y;} int ans[210000]; int main() { init(); bfs(); int m; scanf("%d",&m); for(int i=1;i<=m;i++)scanf("%d%d",&q[i].x,&q[i].y),q[i].id=i; sort(q+1,q+1+m,cmp); int pos=1;int num=0,now=root; int slen=strlen(st+1); for(int i=1;i<=slen;i++) { if(st[i]=='P') { num++; while(q[pos].y==num) { int u=s[q[pos].x]; ans[q[pos].id]=getsum(r[u])-getsum(l[u]-1); pos++; } } else { if(st[i]=='B')change(l[now],-1),now=t[now].fa; else now=t[now].son[st[i]-'a'+1],change(l[now],1); } } for(int i=1;i<=m;i++)printf("%d ",ans[i]); return 0; }
  • 相关阅读:
    System.currentTimeMillis();
    java中synchronized使用方法
    距离矢量路由协议举例——RIP
    Bulk Insert命令具体
    美国地名大全(美国城市名称英文、中文)
    面试准备系列01----面试中的链表题目汇总
    Introspector(内省)简单演示样例 与 简单应用
    Android APK反编译具体解释(附图)
    MATLAB新手教程
    Nginx+Tomcat7+Mencached负载均衡集群部署笔记
  • 原文地址:https://www.cnblogs.com/MT-LI/p/9756261.html
Copyright © 2011-2022 走看看