zoukankan      html  css  js  c++  java
  • 阿狸的打字机(bzoj 2434)

    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
    /*
        第一次做有关fail树的题目。
        fail树就是根据AC自动机上的fail指针建的树,树边由fail[i]指向i。
        查询x在y中出现的次数就是在fail树中查询y的子树中x的节点出现的次数。
        用树状数组维护一下。 
    */
    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<cstring>
    #define N 100010
    using namespace std;
    int l[N],r[N],t[N*2],n,m,cnt,T,size=1;
    int head[N],headq[N],pos[N],ans[N];
    int fa[N],a[N][26],point[N];
    char ch[N];
    queue<int> q;
    struct node{
        int v,pre;
    };node e[N],eq[N];
    
    void insert(int u,int v){
        e[++cnt].v=v;e[cnt].pre=head[u];head[u]=cnt;
    }
    void add(int x,int v){
        for(int i=x;i<=T;i+=i&-i) t[i]+=v;
    }
    int query(int x){
        int sum=0;
        for(int i=x;i;i-=i&-i) sum+=t[i];
        return sum;
    }
    void trie(){
        int now=1,id=0;
        for(int i=0;i<n;i++)
            if(ch[i]=='P') pos[++id]=now;
            else if(ch[i]=='B') now=fa[now];
            else {
                int t=ch[i]-'a';
                if(!a[now][t]){
                    a[now][t]=++size;
                    fa[a[now][t]]=now;
                }
                now=a[now][t];
            }
    }
    void build(){
        q.push(1);point[1]=0;
        while(!q.empty()){
            int now=q.front();q.pop();
            for(int i=0;i<26;i++){
                if(!a[now][i]) continue;
                int k=point[now];
                while(!a[k][i]) k=point[k];
                point[a[now][i]]=a[k][i];
                q.push(a[now][i]);
            }
        }
    }
    void solve(){
        int now=1,id=0;
        add(l[1],1);
        for(int i=0;i<n;i++)
            if(ch[i]=='P'){
                id++;
                for(int x=headq[id];x;x=eq[x].pre){
                    int t=pos[eq[x].v];
                    ans[x]=query(r[t])-query(l[t]-1);
                }
            }
            else if(ch[i]=='B') add(l[now],-1),now=fa[now];
            else now=a[now][ch[i]-'a'],add(l[now],1);
    }
    void dfs(int x){
        l[x]=++T;
        for(int i=head[x];i;i=e[i].pre)
            dfs(e[i].v);
        r[x]=++T;
    }
    int main(){
        scanf("%s",ch);
        n=strlen(ch);
        for(int i=0;i<26;i++) a[0][i]=1;
        trie();build();
        for(int i=1;i<=size;i++)
            insert(point[i],i);
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            int x,y;scanf("%d%d",&x,&y);
            eq[i].v=x;
            eq[i].pre=headq[y];
            headq[y]=i;
        }
        dfs(0);
        solve();
        for(int i=1;i<=m;i++) printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    使用 yo 命令行向导给 SAP UI5 应用添加一个新的视图
    SAP Fiori Elements 应用的 manifest.json 文件运行时如何被解析的
    SAP UI5 标准应用的多语言支持
    微软 Excel 365 里如何设置下拉菜单和自动高亮成指定颜色
    SAP Fiori Elements 应用里的 Title 显示的内容是从哪里来的
    本地开发好的 SAP Fiori Elements 应用,如何部署到 ABAP 服务器上?
    如何在 Cypress 测试代码中屏蔽(Suppress)来自应用代码报出的错误消息
    教你一招:让集群慢节点无处可藏
    应用架构步入“无服务器”时代 Serverless技术迎来新发展
    MySQL数据库事务隔离性的实现
  • 原文地址:https://www.cnblogs.com/harden/p/6551073.html
Copyright © 2011-2022 走看看