zoukankan      html  css  js  c++  java
  • 洛谷 P3805【模板】manacher算法

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

    Manacher算法$O(n)$:

    求以每个字符为中心的最长回文串的半径:
    如果要求可以以字符间隙为回文中心,就要在每两个字符之间加入一个’#’,在开头加上'$',然后再解决。

    $pos$表示回文字串的对称轴,$mx$表示回文串在最右右边界,很明显$2 imes pos-i$即为$i$关于$pos$的对称点。

    令$r_i$为以$i$为中心的最长回文半径。从左往右依次求$r$数组:
    若$i>mx$,即$i$不在所已知的回文串的范围内,那么就让$r_i$从$1$开始计算。

    若$ileq mx$:

      设$j$为$i$关于$pos$的对称点,即$j=(2 imes pos-i)$。

      1),若$r_j>mx-i$,那么不能保证在mx右边仍为回文,所以这时$r_i=mx-i$。

      2),若$r_jleq mx-i$,那么根据对称性可以直接得到,$r_i=r_j$。

      综上所述,$r_i=min(r_j,mx-i)$。

    然后开始暴力往两边扩展,看看是否满足回文。如果右端点扩展到mx右边,则需要更新$mx$和$pos$。

    最后不难发现,$r_i-1$中的最大值即为答案,即$ans=max(ans,r_i-1)$。

    AC代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 const int maxn=51000050;
     7 char str[maxn],s[maxn];
     8 int r[maxn];
     9 
    10 int manacher(int len){
    11     int t=0,ans=0;
    12     s[0]='$';s[++t]='#';
    13     for(int i=1;i<=len;i++){
    14         s[++t]=str[i];
    15         s[++t]='#';
    16     }
    17     int pos=0,mx=0;
    18     for(int i=1;i<=t;i++){
    19         if(i>mx) r[i]=1;
    20         else r[i]=min(r[2*pos-i],mx-i);
    21         while(i-r[i]>=1&&i+r[i]<=t&&s[i+r[i]]==s[i-r[i]]) r[i]++;
    22         if(i+r[i]>mx){
    23             mx=i+r[i];
    24             pos=i;
    25         }
    26         ans=max(ans,r[i]-1);
    27     }
    28     return ans;
    29 }
    30 
    31 int main(){
    32     scanf("%s",str+1);
    33     printf("%d
    ",manacher(strlen(str+1)));
    34     return 0;
    35 }
    AC代码
  • 相关阅读:
    Android studio 安装,JDK 出错解决方案
    Struts2 一、 视图转发跳转
    @Transactional 注解说明
    基于Schema的AOP 配置使用详解
    CSS滤镜让图片模糊(毛玻璃效果)实例页面
    Struts 2.3.4.1完整示例
    StudentSchema student实例数据库环境搭建
    network is unreachable 解决方案之一
    Oracle 转换函数
    Oracle检查与安装操作内容
  • 原文地址:https://www.cnblogs.com/New-ljx/p/12319190.html
Copyright © 2011-2022 走看看