洛谷P1098 [NOIP2007 提高组] 字符串的展开

Posted 江上舟摇

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P1098 [NOIP2007 提高组] 字符串的展开相关的知识,希望对你有一定的参考价值。

题目链接:https://www.luogu.com.cn/problem/P1098

这个题出的真的很有质量,这个是我见过算是复杂的模拟题了,对付这种题,一丝都不能马虎,要想实现快捷而又简便的代码设计,并且针对于这个题繁琐的各种变量,我们采取STL大法,全局都采取STL大法的题目真的是不多,但这个题真的很值得。

我们必须要熟悉STL库的顺序式容器和关联式容器的STL表述方法,并且熟练应用,STL函数库的熟练应用是每个ACMer和OLer的必备技能,惭愧的是,我现在还没能完全掌握STL库,只能应用一部分,相信在日后的学习中STL的使用会越来越熟练。

我们简单介绍几个STL库:

#include<cctype>

加入这个头文件就可以调用以下函数:

1、isalpha(x) 判断x是否为字母

2、isdigit(x) 判断x是否为数字

3、islower(x) 判断x是否为小写字母

4、isupper(x) 判断x是否为大写字母

5、isalnum(x) 判断x是否为字母或数字

6、ispunct(x) 判断x是否为标点符号

7、isspace(x) 判断x是否为空格

对于以上函数,如果x符合条件的话,均会返回true,否则返回false

还有以下函数:

1、toupper(x) 如果x是小写字母,将其转换成大写字母

2、tolower(x) 如果x是大写字母,将其转换成小写字母

 

#include<string>

在本题目中用到的有以下几个函数,也是此头文件下比较常用的函数,更多的可以百度以下

1、s.erase(x,y) 表示将字符串s从x位置起删除y个字符

2、s.insert(x,y) 表示将字符串y(或字符y)插入到s的x位置处

3、s.push_back(x) 表示在s的末尾插入字符x

4、reverse(s.begin(),s.end()) 将字符串s翻转

还有数组vector,其实数组的操作和上述的几个差不多,stack栈的使用,queue,list,set,map,deque,multimap.....等等诸多STL的容器以及例如next_permutation,sort等诸多STL函数的使用。

这个题充分使用了STL库并且将容器的作用发挥到极致。

在此中,为了实现cin,cout输入输出流的快速使用以达到节省时间的目的,我们应用了快速输入输出流:ios::sync_with_stdio(false),这样我们就可以随心所欲的使用cin与cout,不用在担心时间的浪费问题。

还有一个细节要注意的是,大量的使用for循环可能复杂度会大大的增加,我们在此使用register定义变量流来获取时间的一种节约,使用register修饰的变量可以提高它的读写速度,一般用于多层循环中。

这个题细节太多了,学到的知识也太多了,不得不说,这个题很有质量,我在此中收获了不少,也再次见证了STL的简便性和威力。

不多解释了,详细的注意事项和代码如下:

 #include<bits/stdc++.h>
 using namespace std;
 int main()
     ios::sync_with_stdio(false);//快速输入输出流 
     int p1,p2,p3;
     string s;
     cin>>p1>>p2>>p3>>s;
     for(register int i=1;i<s.length()-1;i++)    
     //从第二个元素到倒数第二的元素,其余的是负号就直接不用管了                                     
         if(s[i]==\'-\'&&((islower(s[i-1])&&islower(s[i+1])&&s[i-1]<s[i+1])||(isdigit(s[i-1])&&isdigit(s[i+1])&&s[i-1]<s[i+1])))//超长判断 
                                                                                              
             if(p1==1)
                 s.erase(s.begin()+i);//删除负号 
                 string a;//定一个空的字符串用来操作 
                 for(register int k=s[i-1]+1;k<=s[i]-1;k++)
                 //按ascii码顺序 
                     char ch=k;//用来插入 
                     for(register int j=1;j<=p2;j++) //插入p2个 
                     a.push_back(ch);//插到空字符串的队尾 
                 
                 if(p3==2) 
                 reverse(a.begin(),a.end());//调换 
                 s.insert(i,a);//把操作完成的字符串插到删除负号的地方 
             
             else if(p1==2)
                 s.erase(s.begin()+i);//删除负号 
                 string a;//定义一个空字符串来操作 
                 for(register int k=s[i-1]+1;k<=s[i]-1;k++)//按ASCII码顺序 
                 
                     char ch=k;//用来插入的字符 
                     ch=toupper(ch);//转大写 
                     for(register int j=1;j<=p2;j++) 
                     a.push_back(ch);//同上 
                 
                 if(p3==2) 
                 reverse(a.begin(),a.end());
                 s.insert(i,a);
             
             else if(p1==3)
                 s.erase(s.begin()+i);
                 string a;
                 for(register int k=s[i-1]+1;k<=s[i]-1;k++)
                     for(register int j=1;j<=p2;j++) 
                     a.push_back(\'*\');//插入 “*” 
                 if(p3==2) 
                 reverse(a.begin(),a.end());//翻转 
                 s.insert(i,a);
             
         
     
     cout<<s<<endl;
     return 0;
 

 

戒骄戒躁,任重道远

以上是关于洛谷P1098 [NOIP2007 提高组] 字符串的展开的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P1097 统计数字(NOIp2007提高组T1)

洛谷 P1098 字符串的展开

[NOIP2015] 提高组 洛谷P2679 子串

洛谷P1012 [NOIP1998 提高组] 拼数

洛谷P1012 [NOIP1998 提高组] 拼数

[NOIP2009] 提高组 洛谷P1071 潜伏者