正题
luogu 5446
题目大意
定义对折为:以最后一个字符为对称轴翻转
问你一个字符串可能是由那些前缀对折若干次而来的
解题思路
先用Manacher求出回文长度
那么满足以下条件之一的前缀就是可行方案
-
最后一个字符的回文长度加上它的位置为n(后面若干字符和前面满足回文)
-
最后一个字符回文长度等于该字符串的长度,且对折后形成的字符串是可行方案
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 1000010
using namespace std;
int t, n, s[N], l[N], p[N];
string str;
void Manacher()
{int mx = 0, mid = 0;for (int i = 1; i <= n; ++i){if (i < mx) l[i] = min(l[mid * 2 - i], mx - i);else l[i] = 1;while(s[i + l[i]] == s[i - l[i]]) l[i]++;if (i + l[i] > mx){mx = i + l[i];mid = i;}}return;
}
int main()
{scanf("%d", &t);while(t--){cin>>str;n = str.size();s[0] = '#';for (int i = 1; i <= n; ++i)s[i] = str[i - 1];s[n + 1] = 0;Manacher();memset(p, 0, sizeof(p));for (int i = n; i > 0; --i)if (i + l[i] > n || p[i + l[i] - 1] && l[i] == i)//满足条件p[i] = 1;for (int i = 1; i <= n; ++i)if (p[i])printf("%d ", i);putchar(10);}return 0;
}