• bzoj3439: Kpm的MC密码


    开始本来以为是AC自动机,后来发现不行,跳fail的时候没用的状态太多了。

    正解倒着建Trie

    然后答案就在子树里

    dfs序+主席树求子树中第k大

    注意有重串,用链表搞一下

    1A,表扬自己~

    trie和主席树的变量名重了改的好丑。。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    
    struct Trie
    {
        int w[30],last,fail;
        void clean(){memset(w,0,sizeof(w));last=0;}
    }tr[310000];int trlen,next[110000];
    char ss[110000];
    void insert(int id)
    {
        int now=0,len=strlen(ss+1);
        for(int i=len;i>=1;i--)
        {
            int x=ss[i]-'a'+1;
            if(tr[now].w[x]==0)
                tr[now].w[x]=++trlen, tr[trlen].clean();
            now=tr[now].w[x];
        }
        next[id]=tr[now].last;
        tr[now].last=id;
    }
    
    //-------------Trie--------------------
    
    struct chairman_tree
    {
        int lc,rc,c;
    }ch[6100000];int chlen,rt[310000];
    int maketree(int now,int l,int r,int p)
    {
        if(now==0)
        {
            now=++chlen;
            ch[now].lc=ch[now].rc=0;
            ch[now].c=0;
        }
        ch[now].c++;
        if(l==r)return now;
        else
        {
            int mid=(l+r)/2;
            if(p<=mid)ch[now].lc=maketree(ch[now].lc,l,mid,p);
            else       ch[now].rc=maketree(ch[now].rc,mid+1,r,p);
            return now;
        }
    }
    int merge(int x,int y)
    {
        if(x==0||y==0)return x+y;
        ch[x].c+=ch[y].c;
        ch[x].lc=merge(ch[x].lc,ch[y].lc);
        ch[x].rc=merge(ch[x].rc,ch[y].rc);
        return x;
    }
    //init~~~~~~~
    
    int getk(int x,int y,int l,int r,int k)
    {
        if(k>ch[y].c-ch[x].c)return -1;
        if(l==r)return l;
        
        int lsum=ch[ch[y].lc].c-ch[ch[x].lc].c;
        int mid=(l+r)/2;
        if(lsum>=k)return getk(ch[x].lc,ch[y].lc,l,mid,k);
        else        return getk(ch[x].rc,ch[y].rc,mid+1,r,k-lsum);
    }
    
    //--------------chairman tree-----------------
    
    const int m=1001000;
    int z,l[310000],r[310000];
    int hh[110000];
    void dfs(int now)
    {
        l[now]=++z;
        
        for(int k=tr[now].last;k;k=next[k])
        {
            rt[z]=maketree(rt[z],1,m,k);
            hh[k]=now;
        }
        rt[z]=merge(rt[z],rt[z-1]);
        
            
        for(int x=1;x<=26;x++)
        {
            int son=tr[now].w[x];
            if(son!=0)dfs(son);
        }
        
        r[now]=z;
    }
    
    int main()
    {
        int n;
        scanf("%d",&n);
        trlen=0;tr[trlen].clean();
        for(int i=1;i<=n;i++)
        {
            scanf("%s",ss+1);
            insert(i);
        }
        memset(rt,0,sizeof(rt));
        z=0;dfs(0);
        
        int k;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&k);
            printf("%d
    ",getk(rt[l[hh[i]]-1],rt[r[hh[i]]],1,m,k));
        }
        return 0;
    }
  • 相关阅读:
    JS中的一些遍历方法
    JS中关于引用类型数据及函数的参数传递
    JS中关于数组的操作
    CSS中的一些伪类
    JS中的回调函数
    JS中关于构造函数、原型链、prototype、constructor、instanceof、__proto__属性
    JDK的安装及环境变量配置
    JS中的this指针
    JS中的数据类型
    Word中页码及目录、参考文献的制做方法
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/8873439.html
Copyright © 2020-2023  润新知