题目描述

在初赛普及组的“阅读程序写结果”的问题中,我们曾给出一个字符串展开的例子:如果在输入的字符串中,含有类似于“d-h”或“4-8”的子串,我们就把它当作一种简写,输出时,用连续递增的字母或数字串替代其中的减号,即,将上面两个子串分别输出为“defgh”和“45678”。在本题中,我们通过增加一些参数的设置,使字符串的展开更为灵活。具体约定如下:
(1)遇到下面的情况需要做字符串的展开:在输入的字符串中,出现了减号“-”,减号两侧同为小写字母或同为数字,且按照ASCII码的顺序,减号右边的字符严格大于左边的字符。
(2)参数p1:展开方式。p1=1时,对于字母子串,填充小写字母;p1=2时,对于字母子串,填充大写字母。这两种情况下数字子串的填充方式相同。p1=3时,不论是字母子串还是数字子串,都用与要填充的字母个数相同的星号“*”来填充。
(3)参数p2:填充字符的重复个数。p2=k表示同一个字符要连续填充k个。例如,当p2=3时,子串“d-h”应扩展为“deeefffgggh”。减号两侧的字符不变。
(4)参数p3:是否改为逆序:p3=1表示维持原有顺序,p3=2表示采用逆序输出,注意这时仍然不包括减号两端的字符。例如当p1=1、p2=2、p3=2时,子串“d-h”应扩展为“dggffeeh”。
(5)如果减号右边的字符恰好是左边字符的后继,只删除中间的减号,例如:“d-e”应输出为“de”,“3-4”应输出为“34”。如果减号右边的字符按照ASCII码的顺序小于或等于左边字符,输出时,要保留中间的减号,例如:“d-d”应输出为“d-d”,“3-1”应输出为“3-1”。

输入描述:

第1行为用空格隔开的3个正整数,依次表示参数p1,p2,p3。
第2行为一行字符串,仅由数字、小写字母和减号“-”组成。行首和行末均无空格。

输出描述:

输出一行,为展开后的字符串。

示例1

输入
1 2 1
abcs-w1234-9s-4zz
输出
abcsttuuvvw1234556677889s-4zz

示例2

输入
2 3 2
a-d-d
输出
aCCCBBBd-d

示例3

输入
3 4 2
di-jkstra2-6
输出
dijkstra2************6

备注

40%的数据满足:字符串长度不超过5
100%的数据满足:1 ≤ p1 ≤ 3, 1 ≤ p2 ≤ 8, 1 ≤ p3 ≤ 2。字符串长度不超过100

解答

这是一道比较考验细节的模拟题,需要分的情况很多。
首先是坑点:

  1. 除了题目中提到的几个特殊情况之外,样例1中还出现了一种特殊情况:当‘-’两端的字符分别是数字和字母时,原样输出。
  2. 字符串首尾的‘-’需要原样输出。
  3. 连续的‘-’需要原样输出。

然后就是整体思路了,主函数输入三个参数之后,读入整个字符串(其实也可以边读边判断,但是这样在本地会将输入输出混在一起,不好调试),特判一下字符串首的'-'字符,接着开始处理剩下的字符。

对于当前字符,分几种情况:

  1. 不是'-'时,
  2. 是'-'但是是最后一位
  3. 是'-'但是下一位也是'-'
  4. 是'-'但是上一位也是'-'
  5. 下一位是可以展开的字符

其中,1-4情况全部原样输出,5情况传参给展开函数

对于展开函数,首先判断能不能展开(即是不是题目所给的几个特殊情况)。特判完成后,观察两端字符是不是子母,如果是字母则根据p1参数改变大小写。接着根据p3来正序或者倒序输出(输出时用p2判断个数,每次输出若p1==3则输出'*')此时就完成了一个展开。

下边是代码:

#include <bits/stdc++.h>//头文件
using namespace std;//命名空间

int p1, p2, p3;//三个参数

//展开函数,参数是两端字符
void printstr(char l, char r)
{
    //若l不小于r或者两端字符类型不同
    if (l >= r || (isdigit(l) && isalpha(r)) || (isdigit(r) && isalpha(r)))
    {
        //原样输出'-'
        printf("-", l, r);
    }
    //若l和r只差1
    else if (l + 1 == r)
    {
        //省略'-'
        return ;
    }
    else//否则,开始展开
    {
        if (isalpha(l))//如果是字母
        {
            //根据p1改变大小写
            if (p1 == 1)
            {
                l = tolower(l);
                r = tolower(r);
            }
            else if (p1 == 2)
            {
                l = toupper(l);
                r = toupper(r);
            }
        }

        if (p3 == 1)//判断正序倒序
        {
            //正序
            for (char i = l + 1; i < r; i++)
            {
                //输出p2个
                for (int n = 0; n < p2; n++)
                {
                    //判断p3情况
                    printf("%c", (p1 == 3)? '*': i);
                }
            }
        }
        else if (p3 == 2)//倒序
        {
            for (char i = r - 1; i > l; i--)
            {
                //输出p2个
                for (int n = 0; n < p2; n++)
                {
                    //判断p3情况
                    printf("%c", (p1 == 3)? '*': i);
                }
            }
        }

    }

}

int main(int argc, char const *argv[])//主函数
{
    scanf("%d%d%d", &p1, &p2, &p3);//输入参数
    string str; cin>>str;//读入字符串

    char l;int start;
    //特判开头的'-'
    for (int i = 0; i < str.size(); i++)
    {
        if (str[i] == '-')
        {
            printf("-");
        }
        else
        {
            start = i;
            break;
        }
    }
    //对于剩余字符
    for (int i = start; i < str.size(); i++)
    {
        //不是'-'时
        if (str[i] != '-')
        {
            printf("%c", str[i]);
        }
        //是'-'但是是最后一位/上\下一位也是'-'
        else if (i + 1 == str.size() || (i + 1 != str.size() && str[i + 1] == '-') || (l == '-'))
        {
            printf("-");
        }
        else//否则可以展开
        {
            printstr(l, str[i + 1]);
        }
        //记录上一位字符
        l = str[i];
    }

    return 0;
}


来源:冻葱Tewi