[Пояснения] P5446 [THUPC2018] и зеленый, и строки (manacher)

[Пояснения] P5446 [THUPC2018] и зеленый, и строки (manacher)

Рассмотрим для строки \ (е \) операции, это сделать его в палиндром строку в палиндром центре последнего узла.

Тогда для местоположения \ (Р \) , если это правильное местоположение, то оно было в два раза , когда длина более чем в два раза , когда исходная строка делает \ (T \) появился один раз.

  • Раз больше , чем один раз первоначальной длины строки, то \ (Р \) является центральным палиндром, а \ (Р \) палиндромным радиус достиг \ (| Т | \)
  • Только два раза больше , чем исходная длина строки, то \ (S \) , что момент времени удвоения \ (р «\) является центральным палиндром, и \ (р» \) палиндромический радиус достиг \ (| T | \) . Однако для того, чтобы обеспечить законность первого умножителя, в этом случае оригинала \ (Р \) палиндромные радиальное положение , чтобы выдержать эту \ (1 \) узел.
  • Три раза до тех пор, ...

Думая рекурсивно, правовую позицию , если и только если эта позиция является радиус палиндром в верхней части правой границы или правой границы его собственной законной и задать радиус верхней границы.

Manacher может быть реализовано, внимание к деталям, каждый символ повозка для не-вспомогательный характер, он был центром палиндром палиндром граничной строки должны быть вторичным характером, следует вычесть \ (1 \) для того , чтобы достичь желаемого эффекта ,

Сложность \ (O (2 \ сумма | S |) \)

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;  typedef long long ll; 
inline int qr(){
      register int ret=0,f=0;
      register char c=getchar();
      while(c<48||c>57)f|=c==45,c=getchar();
      while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
      return f?-ret:ret;
}

const int maxn=1e6+5;
char s[maxn<<1];
bool f[maxn<<1];
int p[maxn<<1],cnt,n;
inline void manacher(){
      s[0]='~',s[cnt=1]='|';
      char c=getchar();
      while(c<'a'||c>'z') c=getchar();
      while(c>='a'&&c<='z') s[++cnt]=c,s[++cnt]='|',c=getchar();
      s[cnt+1]='\0';
      for(int t=1,r=0,mid=0;t<=cnt;++t){
        p[t]=0;
        if(r>=t) p[t]=min(r-t+1,p[(mid<<1)-t]);
        while(s[t-p[t]]==s[t+p[t]]) ++p[t];
        if(t+p[t]-1>r) r=t+p[t]-1,mid=t;
      }
}

int main(){
      n=qr();
      for(int t=1;t<=n;++t){
        manacher();
        f[cnt]=1;
        for(int t=cnt;t;--t) f[t]=0,f[t]=(t+p[t]-1==cnt)||(t-p[t]+1==1&&f[t+p[t]-2]);
        for(int t=2;t<=cnt;t+=2) if(f[t]) printf("%d ",t>>1);
        putchar('\n');
      }
      return 0;
}

рекомендация

отwww.cnblogs.com/winlere/p/11598697.html
рекомендация