AtCoder题解——AtCoder Grand Contest 048——A - atcoder < S

题目相关

题目链接

AtCoder Grand Contest 048 A 题,https://atcoder.jp/contests/agc048/tasks/agc048_a

Problem Statement

Given is a string S consisting of lowercase English letters. Snuke can do the operation of swapping two adjacent characters in S. For example, if S=agc, one operation can change it to gac (by swapping a and g) or acg (by swapping g and c).

Snuke wants to do this operation zero or more times so that atcoder <S holds lexicographically.

  • The definition of the lexicographic relation x<y

Determine whether the objective is achievable. If it is achievable, find the minimum number of operations needed. Solve T test cases in an input file.

Input

Input is given from Standard Input in the following format. The first line of input is as follows:

T

Then, T test cases follow, each of which is in the following format:

S

Output

For each test case, print −1 if the objective is unachievable, and print the minimum number of operations needed if it is achievable. Use one line for each case.

Samples1

Sample Input 1

3
atcodeer
codeforces
aaa

Sample Output 1

1
0
-1

Explaination

  • The first test case: for example, swapping the last two characters makes S=atcodere > atcoder hold.
  • The second test case: before doing any operation, we already have S=codeforces > atcoder.
  • The third test case: no sequence of operations makes S> atcoder hold.

Constraints

  • 1 ≤ T ≤ 100
  • 1 ≤ |S| ≤ 1000
  • S is a string consisting of lowercase English letters.

题解报告

题目翻译

给一个全部由小写字母组成的字符串 S。高桥可以讲相邻的两个字母交换位置,比如字符串 agc,可以 gac(交换 g 和 a 的位置),也可以变为 gca(交换 a 和 c 的位置)。

高桥希望通过零次或者若干次操作,最终能使得字符可以满足 s > atcoder,使用字典序排序。

要求我们知道最少的交换次数。

基础知识

字典序

在数学中,字典或词典顺序(也称为词汇顺序,字典顺序,字母顺序或词典顺序)是基于字母顺序排列的单词按字母顺序排列的方法。也就是说小写字母 a<b<c<...<z。

字符串排序

字符串排序是从头开尾,每个字符按照字典序进行排序。假设我们有两个字符串 a 和 b。

  • 如果 a[i]>b[i],则字符串 a>b;
  • 如果 a[i]<b[i],则字符串 a<b;
  • 如果所有的 a[i]==b[i],则字符串 a==b。

从代码实现角度看,我们可以使用循环遍历字符串 a 和 b,进行每个字符逐一比较;也可以使用 STL 的 string 类,string 类直接重载了比较操作符,相对来说比较简单。

题目分析

本题的核心问题是字符串排序,而且本题是求解方案数,这样本题又变成纯粹的数学题。

我们题目的要求是:移动相邻的两个字符;同时知道最终要比较的字符串是 atcoder。这样我们可以分析出如下规律:

1、第一个字符为 a。根据字典序排序规则可知,没有小写字母能大于 a。

2、第二个字符为 t。根据字典序排序规则可知,排在字母 t 前都小于 t;排列在字母 t 后的,都大于 t。

什么意思?我们来看以下下面的几个实例:

1、b;

2、z;

3、aa;

4、ab;

5、as;

6、at;

7、au;

8、az;

9、ata;

10、atb;

11、atz。

对于实例 1。不需要移动已经满足题目的呀求。

对于实例 2。不需要移动已经满足题目的呀求。

对于实例 3。不管怎么移动,都不可能满足题目的呀求。

对于实例 4。我们只需要我们变为 ba 即可,因为 ba>atcoder。

对于实例 5。我们只需要我们变为 sa 即可,因为 sa>atcoder。

对于实例 6。我们只需要我们变为 ta 即可,因为 ta>atcoder。

对于实例 7。因为 au>atcoder。移动次数为零。

对于实例 8。因为 az>atcoder。移动次数为零。

对于实例 9。我们只需要我们变为 taa 即可,因为 taa>atcoder。注意移动的方法和 4、5、6 不一样,这里我们移动前面。

对于实例 10。我们只需要我们变为 tab 即可,因为 tab>atcoder。注意移动的方法和 4、5、6 不一样,这里我们移动前面。

对于实例 11。我们只需要我们变为 taz 即可,因为 taz>atcoder。注意移动的方法和 4、5、6 不一样,这里我们移动前面。

算法设计

通过上面分析。我们可以分类讨论字符 S 和 atcoder 关系。首先我们看两个特殊情况。

特例一:S 本身已经大于 atcoder

对于这样的输入,已经满足题目要求。因此输出 0。

特例二:S 全部为字母 a

对于这样的输入,参考分析的样例 3,我们知道不管怎么移动都不能满足要求。因此输出 -1。

通例

通过观察,我们假设输入字符串 S 的第零个字符到第 i-1 个字符全部为 a,第 i 个字符为 x。

如果 a[i]<='t',如实例 4、5、6,我们只需要交换字符 a[i] 和 a[0] 就可以满足要求。也就是进行了 i 次交换。

如果 a[i]>'t',如实例 9、10、11,我们只需要交换字符 a[i-1] 和 a[0] 就可以满足要求。也就是进行了 i-1 次交换。

AC 参考代码

这里我使用 string,比较方便。

//https://atcoder.jp/contests/agc048/tasks/agc048_a
//A - atcoder < S
#include <bits/stdc++.h>

using namespace std;


int main() {
    int t;
    cin>>t;

    string str;
    while (t-->0) {
        cin>>str;

        //特例判断
        if (str>"atcoder") {
            cout<<"0\n";
            continue;
        } else {
            string tmp(str.length(), 'a');
            if (str==tmp) {
                cout<<"-1\n";
                continue;
            }
        }

        for (int i=0; i<str.length(); i++) {
            if ('a'==str[i]) {
                continue;
            }
            if (str[i]<='t') {
                cout<<i<<"\n";
                break;
            } else {
                cout<<i-1<<"\n";
                break;
            }
        }
    }
    return 0;
}

时间复杂度

算法的时间复杂度为:O(T*S)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

努力的老周

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

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

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

打赏作者

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

抵扣说明:

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

余额充值