码迷,mamicode.com
首页 > 其他好文 > 详细

loj6626 幼儿园唱歌题

时间:2019-12-08 12:31:02      阅读:86      评论:0      收藏:0      [点我收藏+]

标签:scan   scanf   for   its   ||   http   mat   swap   problem   

题目

不难想到把\(S\)的反串\(S^R\)接到\(S\)后面,这样就可以把\(S[l_1,r_1]\)的前缀转化为\(S^R[n-r_1+1,n-l_1+1]\)的后缀

回文树上两节点的lca就是两个前缀的最长公共回文后缀,于是建出回文树来跑个lca就好了

之后这个lca可能太长了,长度超过了\(\min(r_2-l_2+1,r_1-l_1+1)\),于是我们再倍增往上跳一跳使得长度更小一些就好了

注意把两个串拼起来的时候要插两个特殊字符

代码

1#include<bits/stdc++.h>
#define re register
#define min(a,b) ((a)<(b)?(a):(b))
inline int read() {
    char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
const int maxn=4e5+7;char S[maxn];
int fa[maxn],son[maxn][28],len[maxn],cnt,lst,pos[maxn],lg[maxn],dep[maxn];
int f[20][maxn],n,Q;
inline void ins(int c,int n) {
    int F=lst;
    while(S[n-len[F]-1]!=S[n]) F=fa[F];
    if(!son[F][c]) {
        int p=++cnt,k=fa[F];len[p]=len[F]+2;
        while(S[n-len[k]-1]!=S[n]) k=fa[k];
        fa[p]=son[k][c];son[F][c]=p;dep[p]=dep[fa[p]]+1;f[0][p]=fa[p];
        for(re int i=1;i<=lg[dep[p]];++i) f[i][p]=f[i-1][f[i-1][p]];
    }
    lst=son[F][c];pos[n]=lst;
}
inline int LCA(int x,int y) {
    if(dep[x]<dep[y]) std::swap(x,y);
    for(re int i=lg[dep[x]];i>=0;--i)
        if(dep[f[i][x]]>=dep[y]) x=f[i][x];
    if(x==y) return x;
    for(re int i=lg[dep[x]];i>=0;--i)
        if(f[i][x]!=f[i][y]) x=f[i][x],y=f[i][y];
    return fa[x];
}
inline int get(int x,int l) {
    if(len[x]<=l) return len[x];
    for(re int i=lg[dep[x]];i>=0;--i)
        if(len[f[i][x]]>l) x=f[i][x];
    return len[fa[x]];
}
int main() {
    n=read();Q=read();scanf("%s",S+1);S[0]=-1;for(re int i=1;i<=n;i++) S[i]-='a';
    S[n+1]=26,S[n+2]=27;for(re int i=1;i<=n;i++) S[n+i+2]=S[n-i+1];
    for(re int i=2;i<=n+n+2;i++) lg[i]=lg[i>>1]+1;
    len[1]=-1,fa[0]=1;cnt=1;dep[1]=1;dep[0]=2;
    for(re int i=1;i<=n+n+2;i++) ins(S[i],i);
    for(re int x,y,l1,l2,r1,r2;Q;Q--) {
        l1=read(),r1=read(),l2=read(),r2=read();
        x=pos[r2],y=pos[n+2+n-l1+1];int t=LCA(x,y);
        printf("%d\n",-1*get(t,min(r1-l1+1,r2-l2+1)));
    }
    return 0;
}

loj6626 幼儿园唱歌题

标签:scan   scanf   for   its   ||   http   mat   swap   problem   

原文地址:https://www.cnblogs.com/asuldb/p/12005042.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!