ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[洛谷P5829] 失配树

2020-09-21 22:32:09  阅读:227  来源: 互联网

标签:ch 洛谷 Anc RG KMP fail P5829 include 失配


题目大意

给定一长为 \(n(n\leq 10^6)\) 的字符串 \(s\),\(m(m\leq 5\times 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\n");
        else{
            int Ans=LCA(u,v);
            if(Ans==N+1) Ans=0;
            printf("%d\n",Ans);
        }
    }
    return 0;
}

标签:ch,洛谷,Anc,RG,KMP,fail,P5829,include,失配
来源: https://www.cnblogs.com/AEMShana/p/13709174.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有