• bzoj2434: [Noi2011]阿狸的打字机


    可以说也是很迷了。最近写的字符串的题都很迷。。

    首先看到路牌先写板子AC机,然后迷

    然后???

    回忆一下fail的定义:fail[i]到根形成的字符串是i到根形成的字符串的后缀。

    那么大力跳fail硬搞

    那么题目询问就变成了求在第y个字符串的那条路径上,有多少个节点fail指向的是第x个字符串的最后一个节点。

    根据题解考虑离线搞。

    排序一下,这样我们就可以把询问相同y字符串放在一起做。

    还是不会做。先把后缀树建出来吧。

    诶好像在底部的点都可以对上层的点作出贡献诶,也就是说假如y中的一个点的fail指向x的结尾,那么这个点肯定在x的结尾点的子树里面,那是不是dfs序一下搞个树状数组求答案就行了?

    那就再for一次原串,遇到字符就给它+1,删就-1,到了P就看下现在是第几个字符串,这个时候的树状数组就已经把当前字符串的值记录下来了,找到所对应的询问的x串结尾在哪,把它子树的值求出来就行了。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    char ss[110000];int slen;
    int cnt,chuan[110000];
    struct Trie
    {
        int w[30],fa,fail;
    }tr[510000];int trlen;
    void insert()
    {
        scanf("%s",ss+1);slen=strlen(ss+1);
        
        trlen=0;cnt=0;
        int now=0;
        for(int i=1;i<=slen;i++)
        {
            if(ss[i]=='B')now=tr[now].fa;
            else if(ss[i]=='P')chuan[++cnt]=now;
            else
            {
                int x=ss[i]-'a'+1;
                if(tr[now].w[x]==0)
                    tr[now].w[x]=++trlen, tr[trlen].fa=now;
                now=tr[now].w[x];
            }
        }
    }
    int list[510000];
    void bfs()
    {
        int head=1,tail=2;list[head]=0;
        while(head!=tail)
        {
            int now=list[head];
            for(int x=1;x<=26;x++)
            {
                int son=tr[now].w[x];
                if(son!=0)
                {
                    if(now==0)tr[son].fail=0;
                    else
                    {
                        int p=tr[now].fail;
                        while(p!=0&&tr[p].w[x]==0)p=tr[p].fail;
                        tr[son].fail=tr[p].w[x];
                    }
                    list[tail]=son;
                    tail++;if(tail==505000)tail=1;
                }
            }
            head++;if(head==505000)head=1;
        }
    }
    
    //-----------------AC_machine------------------------
    
    struct node
    {
        int x,y,next;
    }a[510000];int len,last[510000];
    void ins(int x,int y)
    {
        len++;
        a[len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
    }
    int z,l[510000],r[510000];
    void get_dfs(int x)
    {
        l[x]=++z;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            get_dfs(y);
        }
        r[x]=z;
    }
    void makefailtree()
    {
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<=trlen;i++)ins(tr[i].fail,i);
        z=0;get_dfs(0);
    }
    
    //-------------make tree and get dfs---------------------
    
    int s[510000];
    int lowbit(int x){return x&-x;}
    void change(int x,int k)
    {
        while(x<=z)
        {
            s[x]+=k;
            x+=lowbit(x);
        }
    }
    int getsum(int x)
    {
        int ret=0;
        while(x>=1)
        {
            ret+=s[x];
            x-=lowbit(x);
        }
        return ret;
    }
    
    //--------------bit-----------------------
    
    struct query
    {
        int x,y,id;
    }q[110000];int tip;
    bool cmp(query n1,query n2){return n1.y<n2.y;}
    int as[110000];
    int main()
    {
        freopen("type.in","r",stdin);
        freopen("type.out","w",stdout);
        
        insert();bfs();
        makefailtree();
        
        int Q;
        scanf("%d",&Q);
        for(int i=1;i<=Q;i++)
            scanf("%d%d",&q[i].x,&q[i].y),q[i].id=i;
        sort(q+1,q+Q+1,cmp);
        
        tip=1;int p=0,num=0;
        for(int i=1;i<=slen;i++)
        {
            if(ss[i]=='P')
            {
                num++;
                while(q[tip].y==num)
                {
                    int u=chuan[q[tip].x];
                    as[q[tip].id]=getsum(r[u])-getsum(l[u]-1);
                    tip++;
                }
            }
            else if(ss[i]=='B')
                change(l[p],-1),p=tr[p].fa;
            else 
                p=tr[p].w[ss[i]-'a'+1],change(l[p],1);
        }
        
        for(int i=1;i<=Q;i++)printf("%d
    ",as[i]);
        return 0;
    }
  • 相关阅读:
    Adb 命令
    python 属性
    python 计时器
    【网易云课堂工作】什么是本能三元组
    functiontools.partial
    源码
    听总结
    线程和死锁
    加入kendall进入计算
    添加K-CORE值进入运算
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/8681101.html
Copyright © 2020-2023  润新知