题目
题目大意
给定一个字符串S,该字符串是由字符串T经过以下操作得来的:
初始S=T
选定T中的一个字母,删去T中全部该字母,得到新T’;
S+=T’;
重复以上步骤直到T被删完为止。
现在给定结果串S,让你求初始串T和字母的删除顺序。
解题思路
初步分析似乎很复杂,如何确定删去字母,如何确定初始长度,似乎两者有着相互影响的关系。
这是按照题目的意思去正向推理,问题变复杂了。
那么便试试逆向推理。最后的一个T一定是由单一字母组成,倒数第二个由两个,以此类推。显然这样就求得了删除字符串的顺序。
那么有了这个顺序又如何求解初始串?
一拍脑袋!每个字母出现的次数和其删除的次序有关,如果第一个被删去,那么只出现一次,即S中的都是初始的,第二个被删去,S串中的个数便是初始串中的两倍,于是通过该方式就可以得到初始串的长度。
之后再通过模拟来验证。便完成了对该问题的求解。
code
#include<bits/stdc++.h>
using namespace std;
void solve()
{
string s;
cin>>s;
vector<int>m(27,0),a;
for(int i=s.length()-1;i>=0;i--)
{
if(m[s[i]-'a']==0)a.push_back(s[i]);
m[s[i]-'a']++;
}
reverse(a.begin(),a.end());//获得的是倒序,需要翻转
int n=a.size();
int sum=0;
//for(int i=0;i<a.size();i++)cout<<(char)a[i];cout<<endl;
for(int i=0;i<n;i++)
{
if(m[a[i]-'a']%(i+1)==0)sum+=m[a[i]-'a']/(i+1);//确定初始串长度,不能整除,显然无法构造
else
{
cout<<-1<<endl;return ;
}
}
// cout<<sum<<endl;
string ns;
for(int i=0;i<sum;i++)ns+=s[i];
string nss=ns,resu=ns;
for(int i=0;i<a.size();i++)
{
string temp;
for(int j=0;j<nss.length();j++)
{
if(nss[j]==a[i])continue;
temp+=nss[j];
}
resu+=temp;
nss=temp;
}
if(resu==s)//模拟验证
{
cout<<ns<<" ";
for(int i=0;i<a.size();i++)cout<<(char)a[i];cout<<endl;//
}
else cout<<-1<<endl;
}
int main()
{
ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--)solve();
return 0;
}