loj6387 「THUPC2018」绿绿与串串 / String
还是很好做的,大致就是manacher,每个位置为中心的最长回文串要是能抵到最右边就合法,要是能抵到最左边,那这个点的是否合法取决于以这个点为中心的最长回文串的右端点是否合法。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
using namespace std;
int T, n, r[2000005], len;
bool iso[1000005];
char ss[2000005];
vector<int> vec;
int main(){
cin>>T;
while(T--){
scanf("%s", ss);
n = strlen(ss);
len = 2 * n + 1;
for(int i=n; i>=0; i--){
ss[2*i+2] = ss[i];
ss[2*i+1] ='#';
}
ss[0] = '$';
len = 2 * n + 1;
int id=0, mx=0;
for(int i=1; i<len; i++){
if(i<mx) r[i] = min(r[2*id-i], mx-i);
else r[i] = 1;
while(ss[i-r[i]]==ss[i+r[i]]) r[i]++;
if(i+r[i]>mx) mx = i + r[i], id = i;
}
vec.clear();
for(int i=n-1; i>=0; i--){
iso[i] = false;
int tmp=r[(i+1)*2]/2;
if(i+tmp==n) iso[i] = true;
if(i-tmp+1==0) iso[i] = iso[i+tmp-1];
if(iso[i]) vec.push_back(i+1);
}
for(int i=vec.size()-1; i>=0; i--)
printf("%d ", vec[i]);
printf("\n");
}
return 0;
}
拙いものと思えども、
その手に握る其れこそが、
いつか幻想を生んでいく。