zoukankan      html  css  js  c++  java
  • CF666E Forensic Examination

    思路

    线段树合并+广义SAM

    先把所有串都插入SAM中,然后用线段树合并维护right集合,对S匹配的同时离线询问,然后就好啦

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int MAXN = 100100;
    const int MAXlog = 20;
    char s[500500],t[50500];
    int lens,m,q;
    namespace Segment_Tree{
        int Nodecnt=0,root[100100];
        struct Node{
            int lson,rson,maxx,maxnum;
        }Seg[100100*50];
        void pushup(int o){
            if(Seg[Seg[o].lson].maxx>Seg[Seg[o].rson].maxx){
                Seg[o].maxx=Seg[Seg[o].lson].maxx;
                Seg[o].maxnum=Seg[Seg[o].lson].maxnum;
            }
            else if(Seg[Seg[o].rson].maxx>Seg[Seg[o].lson].maxx){
                Seg[o].maxx=Seg[Seg[o].rson].maxx;
                Seg[o].maxnum=Seg[Seg[o].rson].maxnum;
            }
            else if(Seg[Seg[o].rson].maxx==Seg[Seg[o].lson].maxx){
                if(Seg[Seg[o].lson].maxnum<Seg[Seg[o].rson].maxnum){
                    Seg[o].maxx=Seg[Seg[o].lson].maxx;
                    Seg[o].maxnum=Seg[Seg[o].lson].maxnum;
                }
                else{
                    Seg[o].maxx=Seg[Seg[o].rson].maxx;
                    Seg[o].maxnum=Seg[Seg[o].rson].maxnum;
                }
            }
        }
        void merge(int l,int r,int &lroot,int rroot){// rroot -> lroot
            if(lroot*rroot==0){
                lroot=lroot+rroot;
                return;
            }
            if(l==r){
                Seg[lroot].maxx+=Seg[rroot].maxx;
                Seg[lroot].maxnum=l;
                return; 
            }
            int mid=(l+r)>>1;
            merge(l,mid,Seg[lroot].lson,Seg[rroot].lson);
            merge(mid+1,r,Seg[lroot].rson,Seg[rroot].rson);
            pushup(lroot);
        }
        void add(int l,int r,int pos,int &o){
            if(!o)
                o=++Nodecnt;
            if(l==r){
                Seg[o].maxx++;
                Seg[o].maxnum=pos;
                return;
            }
            int mid=(l+r)>>1;
            if(pos<=mid)
                add(l,mid,pos,Seg[o].lson);
            else
                add(mid+1,r,pos,Seg[o].rson);
            pushup(o);
        }
        Node query(int L,int R,int l,int r,int o){
            if(!o)
                return (Node){0,0,0,L};
            if(L<=l&&r<=R)
                return Seg[o];
            int mid=(l+r)>>1;
            if(R<=mid)
                return query(L,R,l,mid,Seg[o].lson);
            else{
                if(L>mid)
                    return query(L,R,mid+1,r,Seg[o].rson);
                else{
                    Node ans,lx=query(L,R,l,mid,Seg[o].lson),rx=query(L,R,mid+1,r,Seg[o].rson);
                    if(lx.maxx>rx.maxx){
                        ans.maxx=lx.maxx;
                        ans.maxnum=lx.maxnum;
                    }
                    else if(rx.maxx>lx.maxx){
                        ans.maxx=rx.maxx;
                        ans.maxnum=rx.maxnum;    
                    }
                    else{
                        if(lx.maxnum<rx.maxnum){
                            ans.maxx=lx.maxx;
                            ans.maxnum=lx.maxnum;
                        }
                        else{
                            ans.maxx=rx.maxx;
                            ans.maxnum=rx.maxnum;
                        }
                    }
                    return ans;
                }
            }
        }
    }
    namespace SAM{
        int Nodecnt=1,trans[MAXN][26],maxlen[MAXN],suflink[MAXN];
        int New_state(int _maxlen,int *_trans,int _suflink){
            ++Nodecnt;
            maxlen[Nodecnt]=_maxlen;
            if(_trans)
                for(int i=0;i<26;i++)
                    trans[Nodecnt][i]=_trans[i];
            suflink[Nodecnt]=_suflink;
            return Nodecnt;
        }
        int add_len(int u,int c){
            if(trans[u][c]){
                int v=trans[u][c];
                if(maxlen[v]==maxlen[u]+1)
                    return v;
                int y=New_state(maxlen[u]+1,trans[v],suflink[v]);
                suflink[v]=y;
                while(u&&trans[u][c]==v){
                    trans[u][c]=y;
                    u=suflink[u];
                }            
                return y;
            }
            else{
                int z=New_state(maxlen[u]+1,NULL,0);
                while(u&&trans[u][c]==0){
                    trans[u][c]=z;
                    u=suflink[u];
                }
                if(!u){
                    suflink[z]=1;
                    return z;
                }
                int v=trans[u][c];
                if(maxlen[v]==maxlen[u]+1){
                    suflink[z]=v;
                    return z;
                }
                int y=New_state(maxlen[u]+1,trans[v],suflink[v]);
                suflink[v]=suflink[z]=y;
                while(u&&trans[u][c]==v){
                    trans[u][c]=y;
                    u=suflink[u];
                }            
                return z;
            }
        }
        void insert(char *s,int len,int inq){
            int last=1;
            for(int i=1;i<=len;i++){
                last=add_len(last,s[i]-'a');
                Segment_Tree::add(1,m,inq,Segment_Tree::root[last]);
                // printf("o=%d
    ",last);
            }
        }
        void debug(void){
            for(int i=1;i<=Nodecnt;i++){
               printf("%d: maxlen=%d suflink=%d
    ",i,maxlen[i],suflink[i]); 
            }
        }   
    }
    namespace parent_tree{
        int fir[100100],v[100100],nxt[100100],cnt,fa[100100][MAXlog];
        void addedge(int ui,int vi){
            ++cnt;
            v[cnt]=vi;
            nxt[cnt]=fir[ui];
            fir[ui]=cnt;
        }
        void build(void){
            for(int i=2;i<=SAM::Nodecnt;i++){
                addedge(SAM::suflink[i],i);
                fa[i][0]=SAM::suflink[i];
            }
        }
        void pre(void){
            build();
            for(int i=1;i<MAXlog;i++){
                for(int j=1;j<=SAM::Nodecnt;j++)
                    fa[j][i]=fa[fa[j][i-1]][i-1];
            }
        }
        void debug(void){
            for(int i=0;i<16;i++){
                for(int j=1;j<=SAM::Nodecnt;j++)
                    printf("fa[%d][%d]=%d
    ",j,i,fa[j][i]);
            }
        }
    }
    struct Ask{
        int l,r,pl,pr,which,times;
    }Q[500500];
    struct table{
        int fir[500500],v[500500],nxt[500500],cnt;
        void add(int u,int num){
            ++cnt;
            v[cnt]=num;
            nxt[cnt]=fir[u];
            fir[u]=cnt;
        }
    }Qr,QN;
    void dfs(int u){
        for(int i=parent_tree::fir[u];i;i=parent_tree::nxt[i]){
            dfs(parent_tree::v[i]);
            Segment_Tree::merge(1,m,Segment_Tree::root[u],Segment_Tree::root[parent_tree::v[i]]);
        }
        for(int i=QN.fir[u];i;i=QN.nxt[i]){
            int o=QN.v[i];
            // printf("id=%d
    ",o);
            Segment_Tree::Node tmp=Segment_Tree::query(Q[o].l,Q[o].r,1,m,Segment_Tree::root[u]);
            Q[o].which=tmp.maxnum;
            Q[o].times=tmp.maxx;
            // printf("which=%d time=%d
    ",Q[o].which,Q[o].times);
        }
    }
    int main(){
        // freopen("test.in","r",stdin);
        // freopen("test.out","w",stdout);
        scanf("%s",s+1);
        lens=strlen(s+1);
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            scanf("%s",t+1);
            SAM::insert(t,strlen(t+1),i);
        }
        // SAM::debug();
        parent_tree::pre();
        // parent_tree::debug();
        scanf("%d",&q);
        for(int i=1;i<=q;i++){
            scanf("%d %d %d %d",&Q[i].l,&Q[i].r,&Q[i].pl,&Q[i].pr);
            Qr.add(Q[i].pr,i);
        }
        int nowlen=0,nowp=1;
        for(int i=0;i<lens;i++){
            // printf("i=%d nowp=%d len=%d
    ",i+1,nowp,nowlen);
            if(SAM::trans[nowp][s[i+1]-'a']){
                nowp=SAM::trans[nowp][s[i+1]-'a'];
                nowlen++;
            }
            else{
                while(nowp&&(SAM::trans[nowp][s[i+1]-'a']==0))
                    nowp=SAM::suflink[nowp];
                if(!nowp){
                    nowp=1;
                    nowlen=0;
                    continue;
                }
                nowlen=SAM::maxlen[nowp]+1;
                nowp=SAM::trans[nowp][s[i+1]-'a'];
            }
            for(int j=Qr.fir[i+1];j;j=Qr.nxt[j]){
                // printf("id=%d
    ",Qr.v[j]);
                int lentmp=Q[Qr.v[j]].pr-Q[Qr.v[j]].pl+1;
                if(nowlen<lentmp)
                    continue;
                int tmpp=nowp;
                for(int k=MAXlog-1;k>=0;k--)
                    if(SAM::maxlen[parent_tree::fa[tmpp][k]]>=lentmp)
                        tmpp=parent_tree::fa[tmpp][k];
                QN.add(tmpp,Qr.v[j]);
                // printf("getNode=%d
    ",tmpp);
            }
        }
        dfs(1);
        for(int i=1;i<=q;i++){
            if(Q[i].times)
                printf("%d %d
    ",Q[i].which,Q[i].times);
            else
                printf("%d %d
    ",Q[i].l,Q[i].times);
        }
        return 0;
    }
    
  • 相关阅读:
    HDU 3951 (博弈) Coin Game
    HDU 3863 (博弈) No Gambling
    HDU 3544 (不平等博弈) Alice's Game
    POJ 3225 (线段树 区间更新) Help with Intervals
    POJ 2528 (线段树 离散化) Mayor's posters
    POJ 3468 (线段树 区间增减) A Simple Problem with Integers
    HDU 1698 (线段树 区间更新) Just a Hook
    POJ (线段树) Who Gets the Most Candies?
    POJ 2828 (线段树 单点更新) Buy Tickets
    HDU 2795 (线段树 单点更新) Billboard
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10724796.html
Copyright © 2011-2022 走看看