• bzoj2434: [Noi2011]阿狸的打字机 ac自动机+树状数组


    bzoj2434
    阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有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个询问的答案。

    先建成ac自动机,离线所有查询,记录在树上的终点,把fail树抠出来,先建成dfs序,然后在tire图上跑,当跑到x节点时,root->x节点每个权值为1,(进加1,出减1即可,树状数组单点加),然后利用之前的dfs序查询当前节点fail上的子树总权值和是多少(树状数组查询),因为x在fail树的子树任意节点通过fail上暴跳可以到达x,此时加到的每一个点又是root->x的点,就说明root->x中的节点通过在fail树上暴跳能到达x,记录答案输出即可
    这题还有一个问题就是不能先处理出所有子串,插入直接在trie树上跑就好了,需要记录一个fa,p就打个标记,b就跳fa,否则就向下跳

    /**************************************************************
        Problem: 2434
        User: walfy
        Language: C++
        Result: Accepted
        Time:1120 ms
        Memory:171844 kb
    ****************************************************************/
     
    //#pragma comment(linker, "/stack:200000000")
    //#pragma GCC optimize("Ofast,no-stack-protector")
    //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    //#pragma GCC optimize("unroll-loops")
    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define vi vector<int>
    #define mod 1000000007
    #define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define pil pair<int,ll>
    #define pli pair<ll,int>
    #define pii pair<int,int>
    #define cd complex<double>
    #define ull unsigned long long
    #define base 1000000000000000000
    #define fio ios::sync_with_stdio(false);cin.tie(0)
     
    using namespace std;
     
    const double eps=1e-6;
    const int N=1000000+10,maxn=5000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
     
    char s[N];
    vector<int>trie[N],ftree[N];
    vector<pair<int,int> >qu[N];
    struct ACM{
        int tot,root;
        int Next[N][26],id[N],fail[N],fa[N];
        int newnode()
        {
            for(int i=0;i<26;i++)Next[tot][i]=-1;
            id[tot]=0;
            return tot++;
        }
        void init()
        {
            tot=0;
            root=newnode();
        }
        void ins()
        {
            int now=root,n=strlen(s),co=0;
            for(int i=0;i<n;i++)
            {
                if('a'<=s[i]&&s[i]<='z')
                {
                    if(Next[now][s[i]-'a']==-1)
                    {
                        Next[now][s[i]-'a']=newnode();
                        trie[now].pb(Next[now][s[i]-'a']);
                    }
                    fa[Next[now][s[i]-'a']]=now;
                    now=Next[now][s[i]-'a'];
                }
                else if(s[i]=='P')id[++co]=now;//,printf("%d %d
    ",co,now);
                else now=fa[now];
            }
        }
        void build()
        {
            queue<int>q;
            fail[root]=root;
            for(int i=0;i<26;i++)
            {
                if(Next[root][i]==-1)Next[root][i]=root;
                else
                {
                    fail[Next[root][i]]=root;
                    ftree[root].pb(Next[root][i]);
                    q.push(Next[root][i]);
                }
            }
            while(!q.empty())
            {
                int now=q.front();q.pop();
                for(int i=0;i<26;i++)
                {
                    if(Next[now][i]==-1)Next[now][i]=Next[fail[now]][i];
                    else
                    {
                        fail[Next[now][i]]=Next[fail[now]][i];
                        ftree[Next[fail[now]][i]].pb(Next[now][i]);
                        q.push(Next[now][i]);
                    }
                }
            }
        }
    }ac;
    struct BIT{
        int sum[N];
        void add(int i,int v)
        {
            for(;i<N;i+=i&(-i))sum[i]+=v;
        }
        int query(int i)
        {
            int ans=0;
            for(;i;i-=i&(-i))ans+=sum[i];
            return ans;
        }
    }b;
    int l[N],r[N],res=0,ans[N];
    void dfsfail(int u)
    {
    //    printf("%d 
    ",u);
        l[u]=++res;
        for(int i=0;i<ftree[u].size();i++)
        {
            int x=ftree[u][i];
            dfsfail(x);
        }
        r[u]=res;
    }
    void dfstrie(int u)
    {
    //    printf("%d
    ",u);
        b.add(l[u],1);
        for(int i=0;i<qu[u].size();i++)
        {
            int x=qu[u][i].fi;
            ans[qu[u][i].se]=b.query(r[x])-b.query(l[x]-1);
        }
        for(int i=0;i<trie[u].size();i++)
        {
            int x=trie[u][i];
            dfstrie(x);
        }
        b.add(l[u],-1);
    }
    int main()
    {
        scanf("%s",s);
        ac.init();
        ac.ins();
        ac.build();
    //    for(int i=0;i<ac.tot;i++)
    //    {
    //        for(int j=0;j<ftree[i].size();j++)
    //            printf("%d ",ftree[i][j]);
    //        printf("---%d
    ",i);
    //    }
        int m;scanf("%d",&m);
        for(int i=0;i<m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            x=ac.id[x],y=ac.id[y];
            qu[y].pb(mp(x,i));
        }
        dfsfail(ac.root);
        dfstrie(ac.root);
        for(int i=0;i<m;i++)printf("%d
    ",ans[i]);
        return 0;
    }
    /********************
    aPaPBbP
    3
    1 2
    1 3
    2 3
    ********************/
    
  • 相关阅读:
    ArrayList removeRange方法分析
    LinkedHashMap源码分析(基于JDK1.6)
    LinkedList原码分析(基于JDK1.6)
    TreeMap源码分析——深入分析(基于JDK1.6)
    51NOD 2072 装箱问题 背包问题 01 背包 DP 动态规划
    51 NOD 1049 最大子段和 动态规划 模板 板子 DP
    51NOD 1006 最长公共子序列 Lcs 动态规划 DP 模板题 板子
    8月20日 训练日记
    CodeForces
    CodeForces
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/9293240.html
Copyright © 2020-2023  润新知