题目描述
在初赛普及组的“阅读程序写结果”的问题中,我们曾给出一个字符串展开的例子:如果在输入的字符串中,含有类似于“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)遇到下面的情况需要做字符串的展开:在输入的字符串中,出现了减号“-”,减号两侧同为小写字母或同为数字,且按照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-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; }