LOJ6387 [THUPC2018] 绿绿与串串 【manacher】

时间:2023-03-09 22:48:52
LOJ6387 [THUPC2018] 绿绿与串串 【manacher】

题目分析:

比较简单,先跑一边manacher,然后对于回文部分可以碰到末尾的一定满足条件,否则向后转移。

代码:

 #include<bits/stdc++.h>
using namespace std; const int maxn = ; char str[maxn],solve[maxn<<];
int f[maxn<<],n; void manacher(){
memset(f,,sizeof(f));
for(int i=*n-,j=n-;i>=;i-=,j--){
solve[i] = str[j];solve[i-] = '$';
}
solve[] = str[];
f[] = ; n = *n-;
int fr = ,last = ;
for(int i=;i<n;i++){
if(last + fr >= i){
if(last-(i-last)-f[last-(i-last)]+ >= last- fr)f[i]=min(n-i,f[last-(i-last)]);
else f[i] = min(n-i,last+fr-i+);
while(i-f[i]>=&&f[i]+i<n&&solve[f[i]+i]==solve[i-f[i]])
f[i]++;
if(i+f[i]- >= last+fr) last = i,fr = f[i]-;
}else{
f[i] = ;
while(i-f[i]>=&&f[i]+i<n&&solve[f[i]+i]==solve[i-f[i]]) f[i]++;
last = i; fr = f[i]-;
}
}
} int ans[maxn];
void work(){
memset(ans,,sizeof(ans));
n = strlen(str);int trans = n;
manacher(); n = trans;
for(int i=n-;i>=;i--){
int len = (f[i*]+)/;
if(i + len == n) {ans[i] = ;continue;}
if(i - len + == ){ans[i] = ans[i+len-];continue;}
}
for(int i=;i<n;i++) if(ans[i]) printf("%d ",i+);
puts("");
} int main(){
int t; scanf("%d",&t);
while(t--){
scanf("%s",str);
work();
}
return ;
}