题解:P1098 [NOIP2007 提高组] 字符串的展开

· · 题解

坑较多的字符串模拟题。

其实这题只需要 3 个循环,只要思路正确,码量可以减少很多(虽然还是比不上那些大佬),这里,我来详细讲解一下每个循环的功能。第一个循环是遍历字符串 s 的循环,在循环的过程中判断这一项是否是减号,再判断减号的左右是否越界、左右两个字符是否符合题目中的条件。是则进入下一轮循环。第二轮循环用来枚举左右两个字符中间(不包括本身)的字符,可以用三目运算符等方式减少判断(这样可以让原序和倒序只用一个循环),第三层枚举填充字符的重复个数 p_2 ,再判断是否要做转换大小写、填充星号的操作。最终输出循环中所记录的字符串即可。这样做的好处是题目描述中的第五点我们不用考虑了,因为如果减号右边的字符恰好是左边字符的后继,那么第二个循环就不会执行内部代码,也就不会造成影响。而如果减号右边的字符按照 ASCII 码的顺序小于或等于左边字符,那么就不会进入第二个循环。

注意点:由于这一切不分字母、数字,所以在第三个循环里有可能会遇到展开的是数字但是 p_1 2 的情况,因为数字不能转换大写,所以这里需要特判。

# include <bits/stdc++.h>
using namespace std;
int p1, p2, p3;
string s, z = "";
int main (){
    cin >> p1 >> p2 >> p3 >> s;
    for (int i = 0; i < s.size(); i++){
        if (s[i] == '-' && i < s.size() - 1 && i > 0 && ((s[i - 1] >= '0' && s[i - 1] <= '9' && s[i + 1] >= '0' && s[i + 1] <= '9' && s[i - 1] < s[i + 1]) || (s[i - 1] >= 'a' && s[i - 1] <= 'z' && s[i + 1] >= 'a' && s[i + 1] <= 'z' && s[i - 1] < s[i + 1]))){
            for (char j = (s[i - 1 + 2 * (p3 == 2)] + 1 - 2 * (p3 == 2)); (p3 == 1 ? j <= s[i + 1] - 1 : j >= s[i - 1] + 1); (p3 == 1 ? j++ : j--)){
                for (int k = 1; k <= p2; k++){
                    if (p1 == 1){
                        z += j;
                    }else if (p1 == 2 && j >= 'a' && j <= 'z'){
                        z += (j - 32);
                    }else if (p1 == 3){
                        z += '*';
                    }else{
                        z += j;
                    }
                }
            }
        }else{
            z += s[i];
        }
    }
    cout << z;
    return 0;
}

记录