E. Polycarp and String Transformation- 思维 - 暴力 - 字符串

Problem - E - Codeforces

E. Polycarp and String Transformation

time limit per test

3.0 s

memory limit per test

256 megabytes

input

standard input

output

standard output

Polycarp has a string ss. Polycarp performs the following actions until the string ss is empty (tt is initially an empty string):

  • he adds to the right to the string tt the string ss, i.e. he does t=t+st=t+s, where t+st+s is a concatenation of the strings tt and ss;
  • he selects an arbitrary letter of ss and removes from ss all its occurrences (the selected letter must occur in the string ss at the moment of performing this action).

Polycarp performs this sequence of actions strictly in this order.

Note that after Polycarp finishes the actions, the string ss will be empty and the string tt will be equal to some value (that is undefined and depends on the order of removing).

E.g. consider ss="abacaba" so the actions may be performed as follows:

  • tt="abacaba", the letter 'b' is selected, then ss="aacaa";
  • tt="abacabaaacaa", the letter 'a' is selected, then ss="c";
  • tt="abacabaaacaac", the letter 'c' is selected, then ss="" (the empty string).

You need to restore the initial value of the string ss using only the final value of tt and find the order of removing letters from ss.

Input

The first line contains one integer TT (1≤T≤1041≤T≤104) — the number of test cases. Then TT test cases follow.

Each test case contains one string tt consisting of lowercase letters of the Latin alphabet. The length of tt doesn't exceed 5⋅1055⋅105. The sum of lengths of all strings tt in the test cases doesn't exceed 5⋅1055⋅105.

Output

For each test case output in a separate line:

  • −1−1, if the answer doesn't exist;
  • two strings separated by spaces. The first one must contain a possible initial value of ss. The second one must contain a sequence of letters — it's in what order one needs to remove letters from ss to make the string tt. E.g. if the string "bac" is outputted, then, first, all occurrences of the letter 'b' were deleted, then all occurrences of 'a', and then, finally, all occurrences of 'c'. If there are multiple solutions, print any one.

Example

input

Copy

7
abacabaaacaac
nowyouknowthat
polycarppoycarppoyarppyarppyrpprppp
isi
everywherevrywhrvryhrvrhrvhv
haaha
qweqeewew

output

Copy

abacaba bac
-1
polycarp lcoayrp
is si
everywhere ewyrhv
-1
-1

Note

The first test case is considered in the statement.

---------------------------------------------------------------------------------------------------------------------------------

给出的T便是一个完整串S外加若干残缺S连接而成的,那么其包含的字母种类应该是等于S的

这样我们统计T的字母种类就获得了原字符串的字母种类。且容易发现,设每个字母在S中出现了cnt[x]次,那么 ,第一个被删掉的字母在T中出现了cnt[x]次,第二个出现了2*cnt[x]次,最后一个删除的字母,出现了 m*cnt[x]次,其中m为S中的全部字母种类。

那么如何获取删除字母的顺序呢,显然是倒序遍历,一旦遍历到一个新的字母,那么必定是新删除的,这样我们就可以比对一下整除关系,来初步确认是否合格

但这样我们仅能过掉五个样例,第六个是不行的,第六个是满足个数,但不满足原串顺序,不如暴力枚举出来按步骤删除的全部结果,因为字母本身就只有26个,不会超过26个结果的。暴力优化为,对于当前遍历的字母,如果不是第一个删除的那么就在第一个答案串中加上该字母,如果不是第一个且不是第二个,那么就在第二个答案串中加上该字母,这是个可以用一个26次循环来达成,一旦中间不满足条件,立马终止即可。

最后我们把预处理的串暴力匹配即可,由于我们之前比对了整除关系,在字符数量上,全部答案串的和一定等于T,故不需要担心匹配出现中途不够的情况。

# include<bits/stdc++.h>

using namespace std;
typedef long long int ll;


string s;
int book[210],cnt[210],nowcnt[210];
vector<char>ans;
string yu[210];
int main ()
{


int t;
cin>>t;
while(t--)
{

    cin>>s;
    memset(cnt,0,sizeof(cnt));
    memset(book,0,sizeof(book));
    memset(nowcnt,0,sizeof(nowcnt));
    ans.clear();
    for(int i=0;i<s.length();i++)
    {
        cnt[s[i]]++;
    }
    int k=0;

    for(int i=1;i<=200;i++)
    {
        if(cnt[i])
            k++;
    }int flag=0;
    for(int i=s.length()-1;i>=0;i--)
    {
        if(book[s[i]]==0)
        {
            book[s[i]]=1;
            if(cnt[s[i]]%k)
            {
                flag=1;
                break;
            }

            cnt[s[i]]/=k;
            k--;
            ans.push_back(s[i]);
        }
    }
    if(flag)
    {
        cout<<-1<<endl;
        continue;
    }
    else
    {
        string t="";
        int pos=0;



        for(int i=0;i<s.length();i++)
        {
            if(nowcnt[s[i]]<cnt[s[i]])
            {
                nowcnt[s[i]]++;
                pos=i;
            }
            else
            {

                break;
            }
        }
        for(int i=1;i<=200;i++)
        {
            if(nowcnt[i]!=cnt[i])
                flag=1;
        }
        if(flag)
        {
            cout<<-1<<endl;
            continue;
        }

        for(int i=0;i<=26;i++)
        {
            yu[i]="";
        }

    
        for(int i=0;i<=pos;i++)
        {
            for(int j=ans.size()-1;j>=0;j--)
            {
                if(s[i]==ans[j])
                    break;
                yu[j]+=s[i];
            }

        }

       int nowpos=ans.size()-1;
        for(int i=pos+1;i<s.length();i++)
        {

            string now=s.substr(i,yu[nowpos].length());
         
            if(now==yu[nowpos])
            {

                i=i+yu[nowpos].length()-1;
                nowpos--;
            
            }
            else
            {
                flag=1;
                break;
            }

        }

        if(flag==1)
        {
            cout<<-1<<endl;
            continue;
        }
        else
        {
            cout<<s.substr(0,pos+1)<<" ";

            for(int i=ans.size()-1;i>=0;i--)
            {
                cout<<ans[i];
            }

            cout<<endl;
        }


    }
}
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qinsanma and Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值