题目分析:
比较简单,先跑一边manacher,然后对于回文部分可以碰到末尾的一定满足条件,否则向后转移。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 1000020; 5 6 char str[maxn],solve[maxn<<1]; 7 int f[maxn<<1],n; 8 9 void manacher(){ 10 memset(f,0,sizeof(f)); 11 for(int i=2*n-2,j=n-1;i>=2;i-=2,j--){ 12 solve[i] = str[j];solve[i-1] = ‘$‘; 13 } 14 solve[0] = str[0]; 15 f[0] = 1; n = 2*n-1; 16 int fr = 0,last = 0; 17 for(int i=1;i<n;i++){ 18 if(last + fr >= i){ 19 if(last-(i-last)-f[last-(i-last)]+1 >= last- fr)f[i]=min(n-i,f[last-(i-last)]); 20 else f[i] = min(n-i,last+fr-i+1); 21 while(i-f[i]>=0&&f[i]+i<n&&solve[f[i]+i]==solve[i-f[i]]) 22 f[i]++; 23 if(i+f[i]-1 >= last+fr) last = i,fr = f[i]-1; 24 }else{ 25 f[i] = 1; 26 while(i-f[i]>=0&&f[i]+i<n&&solve[f[i]+i]==solve[i-f[i]]) f[i]++; 27 last = i; fr = f[i]-1; 28 } 29 } 30 } 31 32 int ans[maxn]; 33 void work(){ 34 memset(ans,0,sizeof(ans)); 35 n = strlen(str);int trans = n; 36 manacher(); n = trans; 37 for(int i=n-1;i>=0;i--){ 38 int len = (f[i*2]+1)/2; 39 if(i + len == n) {ans[i] = 1;continue;} 40 if(i - len + 1 == 0){ans[i] = ans[i+len-1];continue;} 41 } 42 for(int i=0;i<n;i++) if(ans[i]) printf("%d ",i+1); 43 puts(""); 44 } 45 46 int main(){ 47 int t; scanf("%d",&t); 48 while(t--){ 49 scanf("%s",str); 50 work(); 51 } 52 return 0; 53 }
原文地址:https://www.cnblogs.com/Menhera/p/9070014.html
时间: 2024-10-18 08:32:06