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

    题目描述

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

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

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

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

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

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

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

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·

    这道题是fail树的裸题。利用ac自动机或trie图能构建出trie树上的fail指针,代表与其拥有最长相同后缀的、比他短的位置。

    重点是每个点只有唯一的fail指针

    这就很像树了。(每个点只有唯一的父节点)

    所以我们可以将fail指针反指,形成一棵树,叫fail树

    fail树所具有的性质就是:当前子树中所有点代表的前缀都以当前树根代表的字符串为后缀。

    人话翻译:

    假设每个点对应一个字符串,那么若b点在a点的子树中,a一定是b的后缀。

    现在再来看这道题,问题是求一个子串中有多少个另一个子串,就是问这个子串中的所有前缀以另一串为后缀的有多少个。

    于是上fail树:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 100050
    int n,m,len,tot,rt[N],hed[N],cnt;
    char s[N];
    struct Trie
    {
        int ch[28];
        int fa,fl;
    }tr[N];
    struct EG
    {
        int to,nxt;
    }e[N];
    void ae(int f,int t)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        hed[f] = cnt;
    }
    void trie_pic()
    {
        queue<int>q;
        for(int i=1;i<=26;i++)
            if(tr[0].ch[i])
                q.push(tr[0].ch[i]),ae(0,tr[0].ch[i]);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            for(int i=1;i<=26;i++)
            {
                int &v = tr[u].ch[i];
                if(!v)
                {
                    v = tr[tr[u].fl].ch[i];
                    continue;
                }
                tr[v].fl = tr[tr[u].fl].ch[i];
                ae(tr[v].fl,v);
                q.push(v);
            }
        }
    }
    int tin[N],tout[N],tim;
    void dfs(int u)
    {
        tin[u]=++tim;
        for(int j=hed[u];j;j=e[j].nxt)dfs(e[j].to);
        tout[u]=tim;
    }
    int f[2*N];
    void up(int x,int d)
    {
        if(!x)return ;
        while(x<=200000)
        {
            f[x]+=d;
            x+=(x&(-x));
        }
    }
    int down(int x)
    {
        if(!x)return 0;
        int ret = 0;
        while(x)
        {
            ret+=f[x];
            x-=(x&(-x));
        }
        return ret;
    }
    struct node
    {
        int u,v,id;
    }p[N];
    int ans[N];
    bool cmp(node a,node b)
    {
        return a.v<b.v;
    }
    int main()
    {
        scanf("%s",s+1);
        len = strlen(s+1);
        int u = 0;
        for(int i=1;i<=len;i++)
        {
            if(s[i]>='a'&&s[i]<='z')
            {
                int c = s[i]-'a'+1;
                if(!tr[u].ch[c])tr[u].ch[c]=++tot,tr[tot].fa=u;
                u=tr[u].ch[c];
            }else if(s[i]=='B')
            {
                u = tr[u].fa;
            }else
            {
                rt[++n] = u;
            }
        }
        trie_pic();
        dfs(0);
        scanf("%d",&m);
        for(int i=1;i<=m;i++)scanf("%d%d",&p[i].u,&p[i].v),p[i].id=i;
        sort(p+1,p+1+m,cmp);
        int k = 1,c = 0;
        u = 0;
        for(int i=1;i<=len;i++)
        {
            if(s[i]>='a'&&s[i]<='z')
            {
                int c = s[i]-'a'+1;
                u = tr[u].ch[c];
                up(tin[u],1);
            }else if(s[i]=='B')
            {
                up(tin[u],-1);
                u = tr[u].fa;
            }else
            {
                c++;
                while(p[k].v==c)
                {
                    ans[p[k].id] = down(tout[rt[p[k].u]])-down(tin[rt[p[k].u]]-1);
                    k++;
                }
            }
        }
        for(int i=1;i<=m;i++)printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    【转】Winform窗体显示在父窗体的中间位置几种代码
    【转】图片上传
    【转】Web文件的ContentType类型大全
    【原】FileUpload控件上传文件
    【转】winform编程实现程序最小化到系统托盘代码
    【原】页面跳转以及表单提交中有中文的解决办法
    【转】asp.net弹出窗体大全
    .NET的发展及组成结构
    如何成为一个优秀的程序员?
    设计模式详细系列教程 (二) 创建型模式
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9676086.html
Copyright © 2011-2022 走看看