zoukankan      html  css  js  c++  java
  • BZOJ2434:[NOI2011]阿狸的打字机——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=2434

    https://www.luogu.org/problemnew/show/P2414

    打字机上只有28个按键,分别印有26个小写英文字母和'B'、'P'两个字母。经阿狸研究发现,这个打字机是这样工作的:

    ·输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。

    ·按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。

    ·按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。

    例如,阿狸输入aPaPBbP,纸上被打印的字符如下:

    a aa ab 我们把纸上打印出来的字符串从1开始顺序编号,一直到n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(其中1≤x,y≤n),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。

    阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?

    因为没有前置技能现学了一发fail树,再回头看就是fail树棵题了。

    因为询问x串在y串出现几次,可以直接转化为y串在trie的节点在fail树x串末节点的子树中出现了几次(这个比较绕,但是很好想。)

    而且因为这题特殊的建trie的方式,我们完全可以离线,对y排序,然后重新跑一遍建trie的过程,这样就保证了y的快(顺)速(序)查找。

    那么中间记录y节点的工作就交给树状数组完成即可。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cctype>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const int S=1e5+5;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct trie{
        int a[26],fa,fail;
    }tr[S];
    struct node{
        int to,nxt;
    }e[S];
    struct data{
        int x,y,id;
    }p[S];
    int m,tot,cnt,ed[S],id,head[S];
    int idx,pos[S],a[S],size[S],ans[S];
    char s[S];
    queue<int>q;
    inline bool cmp(data a,data b){
        return a.y<b.y;
    }
    inline void add(int u,int v){
        e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;
    }
    inline int lowbit(int x){return x&(-x);}
    inline void ins(int x,int y){
        for(int i=x;i<=idx;i+=lowbit(i))a[i]+=y;
    }
    inline int qry(int x){
        int res=0;
        for(int i=x;i;i-=lowbit(i))res+=a[i];
        return res;
    }
    void build(){
        int n=strlen(s),now=0;
        for(int i=0;i<n;i++){
            if(s[i]=='P')ed[++id]=now;
            else if(s[i]=='B')now=tr[now].fa;
            else{
                int c=s[i]-'a';
                if(!tr[now].a[c])tr[now].a[c]=++tot;
                tr[tr[now].a[c]].fa=now;
                now=tr[now].a[c];
            }
        }
    }
    void dfs_trie(){
        int n=strlen(s),now=0,r=0,j=1,sum=0;
        for(int i=0;i<n;i++){
            if(s[i]=='P'){
                sum++;
                for(;j<=m;j++){
                    if(p[j].y==sum){
                        int l=pos[ed[p[j].x]],r=l+size[ed[p[j].x]]-1;
                        ans[p[j].id]=qry(r)-qry(l-1);
                    }else break;
                }
            }
            else if(s[i]=='B'){
                ins(pos[now],-1);
                now=tr[now].fa;
            }
            else{
                now=tr[now].a[s[i]-'a'];
                ins(pos[now],1);
            }
        }
    }
    void getfail(){
        tr[0].fail=0;
        for(int i=0;i<26;i++){
            int u=tr[0].a[i];
            if(u){
                tr[u].fail=0;
                q.push(u);
                add(0,u);
            }
        }
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=0;i<26;i++){
                if(tr[u].a[i]){
                    int v=tr[u].a[i];
                    tr[v].fail=tr[tr[u].fail].a[i];
                    q.push(v);
                    add(tr[v].fail,v);
                }else tr[u].a[i]=tr[tr[u].fail].a[i];
            }
        }
        return;
    }
    void dfs_fail(int u){
        pos[u]=++idx;size[u]=1;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].to;
            dfs_fail(v);
            size[u]+=size[v];
        }
    }
    int main(){
        scanf("%s",s);
        build();getfail();dfs_fail(0);
        m=read();
        for(int i=1;i<=m;i++){
            p[i].x=read(),p[i].y=read(),p[i].id=i;
        }
        sort(p+1,p+m+1,cmp);
        dfs_trie();
        for(int i=1;i<=m;i++)printf("%d
    ",ans[i]);
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    iOS开发之静态库(二)—— .a
    iOS开发之静态库(一)—— 基本概念
    Linux中ctrl-c, ctrl-z, ctrl-d 区别
    JNI技术基础(1)——从零开始编写JNI代码
    开篇纪念
    java面试题
    jvm系列二之GC收集器
    jvm系列一
    ConcurrentHashMap源码剖析(1.8版本)
    博客系统对比
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8997583.html
Copyright © 2011-2022 走看看