CF 1560 E. Polycarp and String Transformation

18 篇文章 0 订阅
12 篇文章 0 订阅

链接

题意:

给出你一个字符串 S S S,然后 T T T初始为空,让你每次将S加进T中,并将 S S S中一个字符全部去除,知道 S S S为空。
例如: S = a b b a b a c S=abbabac S=abbabac
T = a b b a b a c T=abbabac T=abbabac , S S S去除 a a a变成 b b b c bbbc bbbc
T = a b b a b a c b b b c T=abbabacbbbc T=abbabacbbbc S S S去除 b b b变成 c c c
T = a b b a b a c b b b c c T=abbabacbbbcc T=abbabacbbbcc, S S S去除 c c c变成空串退出。
给出你 T T T让你求S和去除字符顺序。找不出来就输出 − 1 -1 1

分析:

昨晚做题脑子缺根筋把’a’写成了’0’导致一直再找BUG,找到最后精疲力尽。改出来这个地方,也结束了。但是思路还是捋的挺清晰的。
首先我我们看去除字符顺序。就拿上面那个字符串吧 T = a b b a b a c b b b c c T=abbabacbbbcc T=abbabacbbbcc这里去除字符串我们用 S T ST ST表示 S T = a b c ST=abc ST=abc,我们看到 T T T最后一个一定 S T ST ST的最后一个。那么我们后面依次找最先出现的字符不就是 S T ST ST的逆序吗?确实是这样的这样我们就得出了 S T ST ST.

得到 S T ST ST串我们就知道他如何删的了,但是还是不好看 S S S字符串,我们再看 T = a b b a b a c b b b c c T=abbabacbbbcc T=abbabacbbbcc,我们第一次删的 a a a,所以 a a a只出现了1次(原串的a个数的1倍)。第二次删的 b b b,所以 b b b出现2次(原串的b个数的2倍),同样我们看 c c c也是出现了三次(原串的c个数的3倍)这样我们只需要把每个字符的数量记录下来,然后除以它对应的位数,看看是否整除,整除的话,那么整除后的这个数就是 S S S拥有这个字符的个数。不整除,肯定就 − 1 -1 1

但是我们写下了之后,发现最后一个样例过不了 q w e q e e w e w qweqeewew qweqeewew,为什么那?因为他按着顺序删后,后面加的顺序不一致,简单的说就是找出来的 S S S S T ST ST不能构成 T T T那怎么办那,我们只需要判断一下就好了,按着题目中给的我们既然已经知道了 S S S S T ST ST那么一定可以构造出来一个 T ′ T' T比较一下 T ′ T' T T T T是否相等就好了。

最后的最后,我们提交后,会发现T5。为什么那? 因为如果 T T T是一个字符循环2e5次,那么我们就会复杂化,我们这拿出来特判下,只有一个字符,直接退出输出就好了。

到此就结束了。
寄语:望大家写代码的时候注意,别因为一些细微的地方像我一样一直在找这个恶毒的小BUG。突然想到了上次做杭电的那道题把 1 < < i 1<<i 1<<i写成了 i < < i i<<i i<<i一直WA,导致心态崩了,最后调了2个半小时左右,调到1点多才调出来,一个题总共时间 读题+思考+写代码都不如调代码的时间长,而且还是细微不能在细微的地方。所以敲代码的时候稍微注意一点,虽然敲代码的时候会多损耗一点时间,但是在敲代码之后就会轻松好多,起码不会有这么低级的错误"绊"你。

string str, s, ans;
map<ll, bool>mp;
int a[30], b[30],c[30];
bool check(string s1,string s2,string s3){
    string tmp="";
    for(int i=0;i<s3.size();i++){
        tmp="";
        for(int j=0;j<s2.size();j++){
            if(s2[j]!=s3[i]) tmp=tmp+s2[j];
        }
        s2=tmp;
        s1+=tmp;
    }
    if(s1==str) return 1;
    return 0;
}

void solve()
{
    mp.clear();
    cin >> str;
    ans = "";
    ll res = 0;
    ll len = str.size();
    for(int i = 0; i < 30; i++) c[i]=b[i] = 0;

    for(int i = 0; i < len; i++)
    {
        if(mp[str[i] - 'a'] == 0)
        {
            mp[str[i] - 'a'] = 1;
            res++;///记录一共多少个不同的字符。
        }
        b[str[i] - 'a']++;/// 
    }
    if(res==1){
        cout<<str<<" "<<str[0]<<endl;
        return ;
    }
    mp.clear();
    ll q=res;
    for(int i = len-1; i >=0; i--)
    {
        if(mp[str[i] - 'a'] == 0)
        {
            mp[str[i] - 'a'] = 1;
            ans=str[i]+ans;///删除顺序
            c[str[i]-'a']=q--;///每次删完一个字符后,他就不循环了。
        }
    }

    
    for(int i = 0; i < 26; i++)
    {
        if(c[i]){
            if(b[i]%c[i]!=0){                
                puts("-1");
                return ;
            }else {
                b[i]=b[i]/c[i];
            }
        }
    }

    ll num = 0;
    for(int i = 0; i < len; i++)
    {
        if(b[str[i] - 'a'] == 1)
        {
            num++;
        }
        if(b[str[i] - 'a'] == 0)
        {
            puts("-1");
            return;
        }
        b[str[i] - 'a']--;
        if(num == res)
        {
            s="";
            for(int j = 0; j <= i; j++)
            {
                s=s+str[j];
            }

            if(check(s,s,ans)){            
                cout <<s<< " "<<ans<<endl;
                return ;
            }else {
                puts("-1");
                return ;
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值