zoukankan      html  css  js  c++  java
  • [SHOI2011]双倍回文

    首先我们发现一个双倍回文串当且仅当本身是一个回文串且左右两边都是回文串。

    那么对于右边的回文串,到中心 (i) 时,Manacher 所记录的 maxr 一定大于 (i),如果满足这个条件,那就判断 (i)(i) 关于 mid 的对称串是否有交点,有交点就说明这是双倍回文串。

    时间复杂度 (O(n))

    #include <bits/stdc++.h>
    #define reg register
    #define ll long long
    #define ull unsigned long long
    #define rep(i,a,n) for(reg int (i)=(a);(i)<=(n);++(i))
    #define per(i,a,n) for(reg int (i)=(a);(i)>=(n);(i)--)
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define SZ(x) ((int) (x).size())
    #define debug(typ...) fprintf(stderr, typ)
    using namespace std;
    const int iINF=numeric_limits<int>::max();
    const ll lINF=numeric_limits<ll>::max();
    int fastin() {
      reg int x = 0, ch = getchar(), f = 0;
      while(!isdigit(ch)) (ch == '-') && (f = 1), ch = getchar();
      while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
      return f ? -x : x;
    }
    const int MAXN=5e5+10;
    const int MAXM=1e6+10;
    int n,f[MAXM];
    char s[MAXN],ss[MAXM];
    void work() {
      n=fastin(),scanf("%s",s+1);
      rep(i,1,n) ss[(i<<1)-1]='#',ss[i<<1]=s[i];
      n=(n<<1)+1,ss[n]='#';
      int r=0,mid=0,ans=0;
      for(reg int i=1;i<=n;i+=2) {
        if(i<r) f[i]=min(f[(mid<<1)-i],r-i);
        else f[i]=1;
        if(i<r&&i-f[i]<mid) ans=max(ans,(i-mid)<<1);
        while(i-f[i]>=1&&i+f[i]<=n&&ss[i-f[i]]==ss[i+f[i]]) ++f[i];
        if(i+f[i]>r) r=i+f[i],mid=i;
      }
      printf("%d
    ",ans);
    }
    signed main() {
      int _=1;
      // _=fastin();
      while(_--) work();
      return 0;
    }
    
  • 相关阅读:
    11.3 校内模拟赛
    11.2 模拟赛题解报告
    11.1 校内模拟赛题解报告
    CF710E Generate a String
    CF165E Compatible Numbers
    CF1092F Tree with Maximum Cost
    2021,10,29 模拟赛题解报告
    LCT学习笔记
    FFT 快速傅里叶变换学习笔记
    拉格朗日插值学习笔记
  • 原文地址:https://www.cnblogs.com/Lonely-233/p/13893962.html
Copyright © 2011-2022 走看看