设可能的答案串为p,长为len。p一定是s的一个子串且len|n。
虽然一些p在s中可能被断成若干段,但删掉其中的若干段后,这段区间一定会被全部消掉。
于是枚举p后,可以用f[i][j]表示区间[i,j]是否合法。len不需要整除区间长度,多余的部分要匹配p的前缀(匹配什么后缀啊,大不了从前面开始)。
f[i][j]可以由j-1拼,即 (f[i][j]|=f[i][j-1] && s[j]==p[(l-1)/l+1] (l=j-i+1))。
也可以是j和前面构成了可消除的串,之后可以跳过这些串继续匹配,即 (f[i][j]|=f[i][j-k*len] && f[j-k*len+1][j])。
第二种转移的上界是(O(frac{n}{len}))的。
复杂度约是(O(sum_{len|n}(n-len+1)*n^2*n/len)=O(n^4))。对p判一下重,再判字符集合法性,跑的就很快了。
//285ms 17216kb(string怎么那么快。。)
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
#define mod (20000000)
const int N=205;
int n,q[N*N],cnt[233],cnt2[233];
bool vis[20000001],f[N][N];
char s[N],p[N],ans[N];
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline int Hash(int l)
{
int x=0;
for(int i=1; i<=l; ++i) x=(x*37+p[i]-'A')%mod;
return x;
}
void Update()
{
if(ans[1]=='{') for(int i=1; i<=n; ++i) ans[i]=p[i];
else
{
for(int i=1; i<=n; ++i) if(p[i]>ans[i]) return;
for(int i=1; i<=n; ++i) ans[i]=p[i];
}
}
bool Solve(int len)
{
for(int i=1; i<=n; ++i) f[i][i]=s[i]==p[1];
for(int l=2; l<=n; ++l)
{
for(int i=1,j; (j=i+l-1)<=n; ++i)
{
f[i][j]=0;
if(f[i][j-1]&&s[j]==p[(l-1)%len+1]) f[i][j]=1;
else
for(int k=1; j>=i+k*len; ++k)
if(f[i][j-k*len]&&f[j-k*len+1][j]) {f[i][j]=1; break;}
}
}
return f[1][n];
}
int main()
{
for(int T=read(); T--; )
{
ans[1]='{'; int t=0;
scanf("%s",s+1), n=strlen(s+1);// cin>>s; s=""+s;
for(int i=1; i<=n; ++i) ++cnt[s[i]];
for(int len=1; len<=n; ++len)
if(!(n%len))
{
for(int l=0,val; l+len<=n; ++l)
{
for(int i=1; i<=len; ++i) p[i]=s[l+i];// p=s.substr(l+1,l+len)
for(int i=1; i<=len; ++i) ++cnt2[p[i]];
bool f=1;
for(int i='a'; i<='z'; ++i) if(cnt2[i]&&cnt[i]%cnt2[i]) {f=0; break;}//cnt2!=0。。
for(int i=1; i<=len; ++i) --cnt2[p[i]];
if(!f) continue;
if(!vis[val=Hash(len)]) vis[val]=1, q[++t]=val;
else continue;
if(Solve(len)) Update();
}
if(ans[1]!='{') {ans[len+1]=' ', puts(ans+1); break;}
}
for(int i=1; i<=t; ++i) vis[q[i]]=0;
for(int i=1; i<=n; ++i) --cnt[s[i]];
}
return 0;
}