• 洛谷 P4555 [国家集训队]最长双回文串(Manacher)


    题目链接:https://www.luogu.com.cn/problem/P4555

    首先明白两个回文串,那么要使两个回文串成立,那么我们只能把$'#'$作为中间节点。

    然后我们跑一边Manacher,记录$l[],r[]$,$l[i]$表示以$i$开头的最长回文串长度,$r[i]$表示以$i$结尾的最长回文串长度。

    那么到最后我们只需要用线性的时间来枚举$i$,找$l_i+r_i$最大即可。

    但是,在Manacher算法中有局限性:就是我们处理出来的$l,r$都是饱和回文串的,那么我们就要处理不饱和回文串:

    $l[i]=max(l[i],l[i-2]-2)$

    $r[i]=max(r[i],r[i+2]-2)$

    解释一下$1$式,$2$式类似:

    其实都是一个递推的过程,l[i-2]即为上一个$‘#’$的位置,$-2$是因为回文串的对称性。

    AC代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 
     7 const int N=100010;
     8 int p[N*2],l[N*2],r[N*2];
     9 char s[N*2],str[N];
    10 int ans,t;
    11 
    12 void manacher(int len){
    13     s[0]='$'; s[++t]='#';
    14     for(int i=1;i<=len;i++){
    15         s[++t]=str[i];
    16         s[++t]='#';
    17     }
    18     int pos=0,mx=0;
    19     for(int i=1;i<=t;i++){
    20         if(i>mx) p[i]=1;
    21         else p[i]=min(p[2*pos-i],mx-i);
    22         while(i+p[i]<=t&&i-p[i]>=1&&s[i-p[i]]==s[i+p[i]]) p[i]++;
    23         if(i+p[i]>mx){
    24             mx=i+p[i];
    25             pos=i;
    26         }
    27         l[i-p[i]+1]=max(l[i-p[i]+1],p[i]-1);
    28         r[i+p[i]-1]=max(r[i+p[i]-1],p[i]-1);
    29     }
    30 }
    31 
    32 int main(){
    33     scanf("%s",str+1);
    34     manacher(strlen(str+1));
    35     for(int i=3;i<=t;i+=2) l[i]=max(l[i],l[i-2]-2);
    36     for(int i=t;i>=3;i-=2) r[i]=max(r[i],r[i+2]-2);
    37     for(int i=3;i<=t;i+=2) if(l[i]&&r[i]) ans=max(ans,l[i]+r[i]);
    38     printf("%d
    ",ans);
    39     return 0;
    40 }
    AC代码
  • 相关阅读:
    安装、升级pip,但是python -m pip install --upgrade pip报错
    架构即未来阅读笔记3
    第十二周学习总结
    《大型网站技术架构:核心原理与案分析》阅读笔记02
    2021寒假(12)
    2021寒假(10)
    Spark简介
    《大型网站技术架构:核心原理与案分析》阅读笔记01
    2021寒假(9)
    2021寒假(8)
  • 原文地址:https://www.cnblogs.com/New-ljx/p/12333457.html
Copyright © 2020-2023  润新知