CodeForces - 666E: Forensic Examination (SAM 绾挎鏍戝悎骞?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces - 666E: Forensic Examination (SAM 绾挎鏍戝悎骞?相关的知识,希望对你有一定的参考价值。

鏍囩锛?a href='http://www.mamicode.com/so/1/isp' title='isp'>isp   bsp   cto   merge   eve   push   娉ㄦ剰   鍊嶅   

棰樻剰锛?/strong>缁欏畾瀛楃涓睸锛岀劧鍚嶮涓瓧绗︿覆T銆俀娆¤闂紝姣忔缁欏嚭(L,R,l,r)锛岄棶S[l,r]鍦↙鍒癛杩欎簺T瀛楃涓蹭腑锛屽湪鍝釜涓插嚭鐜版渶澶氾紝浠ュ強娆℃暟銆?/p>

鎬濊矾锛?/strong>鎶婃墍鏈変覆寤虹珛SAM锛岀劧鍚庡彲浠ラ€氳繃鍊嶅璧板埌[l,r]鍦⊿AM涓婄殑浣嶇疆p锛岀劧鍚庡湪杩欎釜浣嶇疆p涓婃眰锛屾眰鐨勮繃绋嬪氨鏄竴涓嚎娈垫爲姹傚尯闂存渶鍊笺€?鐜板湪鐨勫叧閿槸寰楀埌绾挎鏍戯紝杩欎釜绾挎鏍戣褰曚簡endpos锛岃繖涓彲浠ョ敤鍚彂寮忓悎骞躲€?nbsp; 

娉ㄦ剰鐜板湪鏄箍涔夊悗缂€鑷姩鏈猴紝涓嶈兘鐢ㄦ嫇鎵戞帓搴忓悎骞剁嚎娈垫爲銆?蹇呴』鐢╢ail鏍慏FS鏉ュ悎骞躲€?涓嶇劧浼氬嚭閿欍€?鍏蜂綋鎴戜篃涓嶇煡閬擄紝涓嶈繃鎴戜及璁℃槸鍥犱负骞夸箟鑷姩鏈洪噷闈㈡湁绌轰覆瀵艰嚧鐨勩€?/p>

鎶€鏈浘鐗? id=
    #include<bits/stdc++.h>
    #define rep2(i,a,b) for(int i=a;i>=b;i--)
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=1100010;
    char c[maxn],t[maxn];
    int rt[maxn],pos[maxn],fcy[maxn],N,M,Q,tot;
    int f[maxn][20],ans,num;
    struct in
        int L,R,Mx,id;
    s[maxn*20];
    void update(int now)
    
        if(s[s[now].L].Mx>=s[s[now].R].Mx) 
            s[now].Mx=s[s[now].L].Mx;
            s[now].id=s[s[now].L].id;
        
        else 
            s[now].Mx=s[s[now].R].Mx;
            s[now].id=s[s[now].R].id;
        
    
    void ins(int &now,int L,int R,int p)
    
        if(!now) now=++tot;
        if(L==R)  s[now].Mx++; s[now].id=L; return ;
        int Mid=(L+R)>>1;
        if(p<=Mid) ins(s[now].L,L,Mid,p);
        else ins(s[now].R,Mid+1,R,p);
        update(now);
    
    void merge(int &now,int x,int y,int L,int R)
    
        if(!x||!y)  now= x|y; return ;
        now=++tot;int Mid=(L+R)>>1;
        if(L==R)  s[now].Mx=s[x].Mx+s[y].Mx; s[now].id=L; return ;
        merge(s[now].L,s[x].L,s[y].L,L,Mid);
        merge(s[now].R,s[x].R,s[y].R,Mid+1,R);
        update(now);
    
    void query(int Now,int L,int R,int l,int r)
    
        if(!Now||l>r) return ;
        if(s[Now].Mx<num) return ;
        if(l<=L&&r>=R) 
            if(s[Now].Mx>num) num=s[Now].Mx,ans=s[Now].id;
            else if(s[Now].Mx==num&&num!=0) ans=min(ans,s[Now].id);
            return ;
        
        int Mid=(L+R)>>1;
        if(l<=Mid) query(s[Now].L,L,Mid,l,r);
        if(r>Mid) query(s[Now].R,Mid+1,R,l,r);
    
    struct SAM
        int ch[maxn][26],fa[maxn],maxlen[maxn],cnt,last;
        int a[maxn],b[maxn];
        void init()
        
            cnt=last=1;
            memset(ch[1],0,sizeof(ch[1]));
        
        void add(int x,int id)
        
            int np=++cnt,p=last; last=np;
            if(id>0) ins(rt[np],1,M,id);
            maxlen[np]=maxlen[p]+1; memset(ch[np],0,sizeof(ch[np]));
            while(p&&!ch[p][x]) ch[p][x]=np,p=fa[p];
            if(!p) fa[np]=1;
            else 
                int q=ch[p][x];
                if(maxlen[q]==maxlen[p]+1) fa[np]=q;
                else 
                   int nq=++cnt; maxlen[nq]=maxlen[p]+1;
                   fa[nq]=fa[q]; fa[q]=fa[np]=nq;
                   memcpy(ch[nq],ch[q],sizeof(ch[q]));
                    while(p&&ch[p][x]==q) ch[p][x]=nq,p=fa[p];
                
            
        
        vector<int>G[maxn];
        void dfs(int u)
        
            for(int i=0;i<G[u].size();i++)
                int v=G[u][i];
                f[v][0]=u; dfs(v);
                merge(rt[u],rt[u],rt[v],1,M);
            
        
        void DFS()
        
            rep(i,2,cnt) G[fa[i]].push_back(i);
            dfs(1);
        
    T;
    void solve()
    
        int L,R,l,r,len;
        scanf("%d%d%d%d",&L,&R,&l,&r);
        len=r-l+1;
        int now=pos[r];
        if(T.maxlen[now]<len) 
            printf("%d %d\n",L,0);
            return ;
        
        for(int i=19;i>=0;i--)
            if(T.maxlen[f[now][i]]>=len) now=f[now][i];
        ans=L; num=0;
        query(rt[now],1,M,L,R);
        printf("%d %d\n",ans,num);
    
    int main()
    
        T.init();
        scanf("%s",t+1);
        N=strlen(t+1); T.last=1;
        rep(i,1,N) T.add(t[i]-鈥?/span>a鈥?/span>,0),pos[i]=T.last;
        scanf("%d",&M);
        rep(i,1,M) 
            T.last=1;
            scanf("%s",c+1); N=strlen(c+1);
            rep(j,1,N) T.add(c[j]-鈥?/span>a鈥?/span>,i);
        
        T.DFS();
        rep(i,1,19) rep(j,2,T.cnt) f[j][i]=f[f[j][i-1]][i-1];
        scanf("%d",&Q);
        while(Q--) solve();
        return 0;
    
View Code

绋嶅井浼樺寲涓€涓嬶紝涓轰簡鐪佺┖闂村拰鏃堕棿锛屼篃鍙互鎵嬪姩鎻掑叆S锛屽嵆S娌℃湁蹇呰鎻掑叆SAM涓€?/p>

#include<bits/stdc++.h>
#define rep2(i,a,b) for(int i=a;i>=b;i--)
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=510010;
char c[maxn],t[maxn];
int rt[maxn],pos[maxn],fcy[maxn],N,M,Q,tot;
int f[maxn][20],ans,num;
struct in
    int L,R,Mx,id;
s[maxn*40];
void update(int now)

    if(s[s[now].L].Mx>=s[s[now].R].Mx) 
        s[now].Mx=s[s[now].L].Mx;
        s[now].id=s[s[now].L].id;
    
    else 
        s[now].Mx=s[s[now].R].Mx;
        s[now].id=s[s[now].R].id;
    

void ins(int &now,int L,int R,int p)

    if(!now) now=++tot;
    if(L==R)  s[now].Mx++; s[now].id=L; return ;
    int Mid=(L+R)>>1;
    if(p<=Mid) ins(s[now].L,L,Mid,p);
    else ins(s[now].R,Mid+1,R,p);
    update(now);

void merge(int &now,int x,int y,int L,int R)

    if(!x||!y)  now= x|y; return ;
    now=++tot;int Mid=(L+R)>>1;
    if(L==R)  s[now].Mx=s[x].Mx+s[y].Mx; s[now].id=L; return ;
    merge(s[now].L,s[x].L,s[y].L,L,Mid);
    merge(s[now].R,s[x].R,s[y].R,Mid+1,R);
    update(now);

void query(int Now,int L,int R,int l,int r)

    if(!Now||l>r) return ;
    if(s[Now].Mx<num) return ;
    if(l<=L&&r>=R) 
        if(s[Now].Mx>num) num=s[Now].Mx,ans=s[Now].id;
        else if(s[Now].Mx==num&&num!=0) ans=min(ans,s[Now].id);
        return ;
    
    int Mid=(L+R)>>1;
    if(l<=Mid) query(s[Now].L,L,Mid,l,r);
    if(r>Mid) query(s[Now].R,Mid+1,R,l,r);

struct SAM
    int ch[maxn][26],fa[maxn],maxlen[maxn],cnt,last;
    int a[maxn],b[maxn];
    void init()
    
        cnt=last=1;
        memset(ch[1],0,sizeof(ch[1]));
    
    void add(int x,int id)
    
        int np=++cnt,p=last; last=np;
        if(id>0) ins(rt[np],1,M,id);
        maxlen[np]=maxlen[p]+1; memset(ch[np],0,sizeof(ch[np]));
        while(p&&!ch[p][x]) ch[p][x]=np,p=fa[p];
        if(!p) fa[np]=1;
        else 
            int q=ch[p][x];
            if(maxlen[q]==maxlen[p]+1) fa[np]=q;
            else 
               int nq=++cnt; maxlen[nq]=maxlen[p]+1;
               fa[nq]=fa[q]; fa[q]=fa[np]=nq;
               memcpy(ch[nq],ch[q],sizeof(ch[q]));
                while(p&&ch[p][x]==q) ch[p][x]=nq,p=fa[p];
            
        
    
    vector<int>G[maxn];
    void dfs(int u)
    
        for(int i=0;i<G[u].size();i++)
            int v=G[u][i];
            f[v][0]=u; dfs(v);
            merge(rt[u],rt[u],rt[v],1,M);
        
    
    void DFS()
    
        rep(i,2,cnt) G[fa[i]].push_back(i);
        dfs(1);
    
T;
void solve()

    int L,R,l,r,len;
    scanf("%d%d%d%d",&L,&R,&l,&r);
    len=r-l+1;
    int now=pos[r];
    if(fcy[r]<len) 
        printf("%d %d\n",L,0);
        return ;
    
    for(int i=19;i>=0;i--)
        if(T.maxlen[f[now][i]]>=len) now=f[now][i];
    ans=L; num=0;
    query(rt[now],1,M,L,R);
    printf("%d %d\n",ans,num);

int main()

    T.init();
    scanf("%s",t+1);
    scanf("%d",&M);
    rep(i,1,M) 
        T.last=1;
        scanf("%s",c+1); N=strlen(c+1);
        rep(j,1,N) T.add(c[j]-鈥?/span>a鈥?/span>,i);
    
    int now=1,len=0; N=strlen(t+1);
    rep(i,1,N) 
        int x=t[i]-鈥?/span>a鈥?/span>;
        if(T.ch[now][x]) now=T.ch[now][x],len++;
        else 
            while(now&&!T.ch[now][x]) now=T.fa[now];
            if(now==0) now=1,len=0;
            else len=T.maxlen[now]+1,now=T.ch[now][x];
        
        pos[i]=now;
        fcy[i]=len;
    
    T.DFS();
    rep(i,1,19) rep(j,2,T.cnt) f[j][i]=f[f[j][i-1]][i-1];
    scanf("%d",&Q);
    while(Q--) solve();
    return 0;

 

以上是关于CodeForces - 666E: Forensic Examination (SAM 绾挎鏍戝悎骞?的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 666E Forensic Examination SAM+权值线段树

[CF 666E] Forensic Examination

CF666E Forensic Examination

CF666E Forensic Examination

[CF666E]Forensic Examination

CF666E Forensic Examination [后缀自动机,线段树合并]

(c)2006-2024 SYSTEM All Rights Reserved IT常识