链接:https://ac.nowcoder.com/acm/problem/16644
来源:牛客网
#include<bits/stdc++.h>
using namespace std;
string solve(char b,char e,int p1,int p2,int p3)
{
if(e-b==1)return "";
if(!(isalpha(b)&&isalpha(e)&&b<e||isdigit(b)&&isdigit(e)&&b<e))
return "-";
string ans="";
for(char i=b+1;i<e;i++)
{
for(int j=1;j<=p2;j++)
{
ans+=i;
}
}
if(p1==2&&isalpha(b))
{
for(int i=0;i<ans.length();i++)
{
ans[i]=ans[i]-'a'+'A';
}
}
if(p1==3)
{
for(int i=0;i<ans.length();i++)
ans[i]='*';
}
if(p3==2){
reverse(ans.begin(),ans.end());
}
return ans;
}
int main()
{
int p1,p2,p3;
cin>>p1>>p2>>p3;
string a;
cin>>a;
string ans="";
for(int i=0;i<a.length();i++)
{
if(a[i]=='-')
{
ans+=solve(a[i-1],a[i+1],p1,p2,p3);
}
else
{
ans+=a[i];
}
}
cout<<ans<<endl;
return 0;
}
- 发现遇到‘-’就会把字符串展开这个操作重复出现,就可以考虑封装一个函数
- 遍历字符串,我的方法是把它往后移,但这显然很麻烦,计算区间长度,复杂度变大。最优的方式是再创建一个字符串 ans 来存答案
- 如果 a [i] 不是 '-'ans 就直接加
- 如果是加上展开的字符串
- 如何展开?先排斥非法的情况
- 第一种非法情况是 "a-b"->"ab","2-3"->"23" 这种,这个情况下,不管是字母还是数字,都可以统一理解为:后面字符比前面的字符 ASCII 码大 1,也就是 e-b == 1,这种情况下返回空字符串 ""(e 表示 '-' 前的字符,b 表示 '-' 后的字符。)
- "减号两侧同为小写字母或同为数字,且按照 ASCII 码的顺序,减号右边的字符严格大于左边的字符。" 从反面入手,正面情况复杂,前字母后数字前数字后字母,到差不多吧
然后就是去写这个 ans
for(char i=b+1;i<e;i++) { for(int j=1;j<=p2;j++) { ans+=i; } }
这个循环很巧妙,第一层是解决哪一个,第二层解决有几个
然后p1=2**并且是字母**的时候,把填好的小写字母变成大写字母。大写字母就不用管了,这里还可以调用函数toupper (这里注意,这个并且是<mark class="hltr-orange">字母一定要判断</mark>,我就在这里wa了一发。)
p1=3没啥
最后反转直接调用函数reverse
上面的代码有错,1. 开头和结尾的‘-’,如“-a-d-”
```c++
if(a[i]=='-'&&i-1>=0&&i+1<a.length())
{
ans+=solve(a[i-1],a[i+1],p1,p2,p3);
}
特殊情况的考虑
- 开头和结尾的‘-’,如 “-a-d-”
- 连续的‘-’,如 “---” 这行代码解决了这个问题
(isalpha(b)&&isalpha(e)&&b<e||isdigit(b)&&isdigit(e)&&b<e))
- 数字和字母之间的‘-’,如 “1-a”
- ‘-’左侧的字符大于右侧的,如 “d-a”