[Пояснения] 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;
}