• 模板:manacher算法


    https://www.luogu.org/problemnew/show/P3805

    回文串长度的奇偶性造成了对称轴的位置可能在某字符上,也可能在两个字符之间的空隙处

    那么manacher对此的优化是在每两个字符中间插入另一个字符,如'#'。

    用一个辅助数组r表示每个点能够扩展出的回文长度

    我们先设置一个辅助变量maxright,表示已经触及到的最右边的字符

    另外还要设置一个辅助变量mid,表示包含maxright的回文串的对称轴所在的位置

    当i在maxright左边且在mid右边时:

    设i关于mid的对称点为j,显然r[i]一定不会小于r[j]。(对称)

    我们没必要保存j,j可以通过计算得出,为:(mid<<1)−i

    那么我们就设置r[i]=r[j]然后继续尝试扩展,这样就可以较快地求出r[i],然后更新maxright和mid

    当i在maxright右边时,我们无法得知关于r[i]的信息,只好从1开始遍历,然后更新maxright和mid

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 char t[11000010], a[11000010];
     6 int n, m, ans=0;
     7 int r[23000000];
     8 int main() {
     9     scanf("%s", t);
    10     m=strlen(t);
    11     a[0]=a[1]='#';
    12     for(int i=1; i<=m; i++){
    13         a[(i<<1)]=t[i-1];
    14         a[(i<<1)+1]='#';
    15     }
    16     n=(m<<1)+2;
    17     int mid=1, maxright=1;
    18     r[1]=1;
    19     for(int i=2; i<n; i++){
    20         if(i<maxright) r[i]=min(r[(mid<<1)-i], r[mid]+mid-i); 
    21         else  r[i]=1;
    22         while(a[i-r[i]]==a[i+r[i]]) r[i]++;
    23         if(i+r[i]>maxright){
    24             maxright=i+r[i];
    25             mid=i;
    26         }
    27         if(r[i]>ans)    ans=r[i];
    28     }
    29     printf("%d
    ", ans-1);
    30     return 0;
    31 }
  • 相关阅读:
    UVa10779
    UVa10779
    C++ 内存管理学习笔记
    c++ 学习笔记
    AcWing 275 传纸条
    I
    Tree HDU6228
    Lpl and Energy-saving Lamps
    C
    Secret Poems
  • 原文地址:https://www.cnblogs.com/Aze-qwq/p/9891115.html
Copyright © 2020-2023  润新知