zoukankan      html  css  js  c++  java
  • [洛谷P5829] 失配树

    题目大意

    给定一长为 (n(nleq 10^6)) 的字符串 (s)(m(mleq 5 imes 10^5))次询问,每次询问它的两个前缀的最长公共 border。

    题解

    先跑一遍KMP求出(fail)数组,每个(pos)(fail[pos])连边,建出(fail)树,在(fail)树上求lca即为两个前缀的最长公共border。

    Code

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <cstdio>
    #include <vector>
    using namespace std;
    
    #define RG register int
    #define LL long long
    
    template<typename elemType>
    inline void Read(elemType &T){
        elemType X=0,w=0; char ch=0;
        while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
        while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        T=(w?-X:X);
    }
    
    const int maxn=1000010;
    
    struct Graph{
        struct edge{int Next,to;};
        edge G[maxn<<1];
        int head[maxn];
        int cnt;
    
        Graph():cnt(2){}
        void clear(int node_num=0){
            cnt=2;
            if(node_num==0) memset(head,0,sizeof(head));
            else fill(head,head+node_num+5,0);
        }
        void add_edge(int u,int v){
            G[cnt].to=v;
            G[cnt].Next=head[u];
            head[u]=cnt++;
        }
    };
    
    namespace KMP{
        int LenP=0,*Fail=NULL;
        char *P=NULL;
        inline void bind_kmp(char *_P,int *_Fail,int _len){
            P=_P;Fail=_Fail;
            LenP=_len;
        }
        inline void get_fail(){//求出Fail数组
            Fail[1]=0;
            for(RG i=2,pos=0;i<=LenP;++i){
                while(pos && (pos==LenP || P[i]!=P[pos+1])) pos=Fail[pos];
                if(P[i]==P[pos+1]) ++pos;
                Fail[i]=pos;
            }
        }
    };
    
    Graph G;
    char s[maxn];
    int Fail[maxn];
    int N,M;
    
    int Deep[1000010],Anc[1000010][20];
    
    void DFS_Init(int u,int fa){
        Anc[u][0]=fa;
        for(int i=1;i<20;++i)
            Anc[u][i]=Anc[Anc[u][i-1]][i-1];
        for(int i=G.head[u];i;i=G.G[i].Next){
            int v=G.G[i].to;
            if(v==fa) continue;
            Deep[v]=Deep[u]+1;
            DFS_Init(v,u);
        }
        return;
    }
    
    int LCA(int u,int v){
        int Root=N+1;
        if(u==Root || v==Root) return Root;
        if(Deep[u]<Deep[v]) swap(u,v);
        for(RG i=19;i>=0;--i){
            if(Deep[Anc[u][i]]>=Deep[v])
                u=Anc[u][i];
        }
        if(u==v) return u;
        for(RG i=19;i>=0;--i){
            if(Anc[u][i]!=Anc[v][i]){
                u=Anc[u][i];
                v=Anc[v][i];
            }
        }
        return Anc[u][0];
    }
    
    int main(){
        scanf("%s",s+1);
        N=strlen(s+1);
        KMP::bind_kmp(s,Fail,N);
        KMP::get_fail();
        for(RG u=1;u<=N;++u){
            int v=Fail[u];
            if(v==0) v=N+1;
            G.add_edge(u,v);
            G.add_edge(v,u);
        }
        DFS_Init(N+1,0);
        Read(M);
        while(M--){
            int u,v;
            Read(u);Read(v);
            u=Fail[u];v=Fail[v]; 
            if(!u || !v) printf("0
    ");
            else{
                int Ans=LCA(u,v);
                if(Ans==N+1) Ans=0;
                printf("%d
    ",Ans);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    hive中使用正則表達式不当导致执行奇慢无比
    C/C++实现正负数四舍五入
    EEPlat的控制器概念
    由于好高骛远所以半途而废(张作作)
    新辰:关于“网络推广不能仅仅依靠网络”的详解
    SQL的事务回滚操作带案例分析
    怎样把引用的jar包和本项目一起导出成jar文件
    A星算法(Java实现)
    Hadoop之——HBASE结合MapReduce批量导入数据
    Spring MVC 数据验证——validate编码方式
  • 原文地址:https://www.cnblogs.com/AEMShana/p/13709174.html
Copyright © 2011-2022 走看看