字符串处理(一)

文章目录

    • 1001.A+B
    • 1005.拼写正确
    • 1006.签到与签出
    • 1035.密码
    • 1036 .男孩VS女孩
    • 1050.字符串减法
    • 1071.说话方式
    • 1061.约会
    • 1016.电话账单 **(结构体排序)
    • 1017.银行排队
    • 1026.乒乓球 **(结构体排序)
    • 1060.他们是否相等 **
    • 1073.科学计数法??
    • 1077.Kuchiguse
    • 1082.中文读数字 **
    • 1084.坏掉的键盘
    • 1108.求平均值
    • 1124.微博转发抽奖
    • 1141.PAT单位排行 ** (结构体排序--多关键字比较)
    • 1153. 解码PAT准考证(pair排序)

1001.A+B

字符串处理(一)_第1张图片

  • 题目意思是让我们输出a+b的值,并且输出格式是每三位加一个逗号
  • 首先将a+b=c 转字符串(to_string ),然后用res存储新串,从后向前遍历,每有三位并且前面一位不是‘-’号就添加一位逗号
#include
#include

using namespace std;

int main(){
     
    
    int a,b;
    
    cin>>a>>b;
    
    int c=a+b;
    
    string num=to_string (c);
    
    string res;
    
    for(int i=num.size()-1,j=0;i>=0;i--){
     
        
        res=num[i]+res;
        
        j++;
        
        if(j%3==0 && i && num[i-1]!='-')res=","+res;     //&& i防止i为0,nums[i-1]报栈溢出 
    }
    
    
    cout<<res;
}


1005.拼写正确

字符串处理(一)_第2张图片

  • 题目要求我们计算输入数字每一位的总和,最后输出总和的每一位英文字母
  • 数字范围过大直接用string读入再转数字计算总和,最后用二维数组映射方式存储每一位数字对应的英文单词

#include
#include
#include

using namespace std;

int main(){
     

    string s;
    
    cin>>s;
    
    int res=0;
    
    for(auto c:s)res+=c-'0';
    
    char word[10][10] = {
     
        "zero", "one", "two", "three", "four",
        "five", "six", "seven", "eight", "nine",
    };
    
    s=to_string (res);
    
    cout<<word[s[0]-'0']<<" ";         //先输出一位,后面输出时直接输出空格+单词,防止结尾出现空格
    
    int len=s.size();
    
    for(int i=1;i<len;i++){
     
        
        cout<<""<<word[s[i]-'0'];
    }
}

1006.签到与签出

字符串处理(一)_第3张图片

  • 注意:cin以空格作为间断分批读入字符串
  • 两时间串长度相同,其大小服从字典序,直接比较即可
#include
#include
#include

using namespace std;

int main(){
     
    
    int n;
    
    cin>>n;
    
    string oid,oti;
        
    string cid,cti;     //定义最后开门人ID,time,关门人id,time
    
    for(int i=0;i<n;i++){
     
        
        string id,eti,lti;       //定义当前输入的id,进出时间
        
        cin>>id>>eti>>lti;
        
        if(!i||eti<oti){
              //因为时间相同且服从字典序,直接比较即可
            
            oid=id;
            
            oti=eti;
        }
        
        if(!i||cti<lti){
     
            
            cid=id;
            
            cti=lti;
        }
        
    }
    
    cout<<oid<<" "<<cid;

}


1035.密码

字符串处理(一)_第4张图片

#include
#include

using namespace std;

const int N=1010;

string x[N];      //存储用户名和密码

int modify(string & s){
          //修改用户密码,如果修改了,返回1,否则返回0
    
    string og=s;
    
    int len=s.size();
    
    int i=0;
    
    while(s[i]!=' ')i++;
    
    for(i=i+1;i<len;i++){
     
        
        if(s[i]=='1')s[i]='@';
        
        if(s[i]=='0')s[i]='%';
        
        if(s[i]=='l')s[i]='L';
        
        if(s[i]=='O')s[i]='o';
    }
    
    if(s==og)return 0;
    
    else  return 1;
}

int main(){
     
    
    int n;
    
    int idx=0;
    
    cin>>n;
    
    while(n--){
     
        
        string id,anw;
        
        cin>>id>>anw;

        if(modify(anw))x[idx++]=id+" "+anw;     //将被修改过的用户名和密码加入数组中
    } 
    
    if(!idx){
     
        if(n==1)cout<<"There is 1 account and no account is modified";
        
        else cout<<"There are "<<n<<" accounts and no account is modified";
    }
    
    else {
     
        
        cout<<idx<<endl;
        
        for(int i=0;i<idx;i++){
     
            
            cout<<x[i]<<endl;
        }
    }

}


1036 .男孩VS女孩

字符串处理(一)_第5张图片

  • 题目是打印成绩最好的女孩和最差的男孩成绩和成绩之差,没有则输出Absent

#include
#include
#include

using namespace  std;

const int N=110;

int posm,posf;

string name[N],sex[N],id[N],score[N];

int to_int(string s){
     
    
    int len=s.size();
    
    int res=0;
    
    for(int i=0;i<len;i++){
     
        
        res=res*10+s[i]-'0';
    }
    
    return res;
}

int main(){
     
    
     int n;
     
     int idx=0;
     
     cin>>n;
     
     int max=-1e9,min=1e9;
     
     while(n--){
     
         
         cin>>name[idx]>>sex[idx]>>id[idx]>>score[idx];
         
         int grade=to_int(score[idx]);

         if(sex[idx]=="F"&& grade>max)max=grade,posf=idx;
         
         if(sex[idx]=="M"&& grade<min)min=grade,posm=idx;
         
         idx++;
     }
     
     bool flag=false;
     
     if(max==-1e9){
     
         
         cout<<"Absent"<<endl;
         
         flag=true;
     }
     
     else  cout<<name[posf]<<" "<<id[posf]<<" "<<endl;
     
     
     if(min==1e9){
     
         
         cout<<"Absent"<<endl;
         
         flag=true;
     }
     
     else  cout<<name[posm]<<" "<<id[posm]<<" "<<endl;
     
     if(flag)cout<<"NA";
     
     else cout<<abs(to_int(score[posf])-to_int(score[posm]));
     
     return 0;
}

1050.字符串减法

字符串处理(一)_第6张图片

  • 题目原意是找到字符串2中所有出现的过的字母在字符串1中删除
  • 两重循环O(n^2)=10^8超时,所以直接使用哈希表优化代码

#include
#include
#include

using namespace std;

int main(){
     
    
    string s1,s2;
    
    getline(cin,s1);
    
    getline(cin,s2);
    
    int len1=s1.size(),len2=s2.size();
    
    map<char,int>  has;
    
    for(int i=0;i<len2;i++)has[s2[i]]++;
 
    
    string res;
    
    for(int i=0;i<len1;i++)if(!has.count(s1[i]))res+=s1[i];
    
    cout<<res;
    
}

1071.说话方式

字符串处理(一)_第7张图片

  • 本题统计次数最多的常用语,且不包含字母和数字以外的所有单词,不区分大小写
  • 题目难点在于如何抠出每一个单词,可以采用类似双指针+substr(i,j)的方式读入每个字符串
#include
#include
#include

using namespace std;

int main(){
     
    
    map<string,int>  has;
    
    string s;
    
    getline(cin,s);
    
    int len=s.size();
    
    string cur;
    
    for(int i=0;i<len;i++){
     

        if(s[i]>='A'&&s[i]<='Z')s[i]+=32;
        
        if((s[i]>='0'&&s[i]<='9')||(s[i]>='a'&& s[i]<='z')){
     
            
            cur+=s[i];
        }
        
        else if(cur.size()) {
     
            
            has[cur]++;
            
            cur="";
        }
    }
    
    if(cur.size())has[cur]++;
    
    int max=0;
    
    string res;
    
    for(auto x :has){
     
        
        if(x.second>max){
     
            
            max=x.second;
            
            res=x.first;
        }
    }
    
    
    cout<<res<<" "<<max;
    
}


  • 双指针的写法
#include
#include
#include

using namespace std;

bool check(char c){
     
    
    if(c>='a'&&c<='z'||c>='A'&&c<='Z'||c>='0'&&c<='9')return true;
    
    else return false;
}

int main(){
     
    
    map <string,int>  has;                        //map自带字典排序
    
    string s;
    
    getline(cin,s);
    
    int len=s.size();
    
    for(int i=0;i<len;i++){
     
        
        string cur;
        
        if(check(s[i])){
     
            
            int j=i;
            
            while(j<len&& check(s[j]))cur+=tolower(s[j++]);    //tolower将字符转化成小写字母
            
            has[cur]++;
            
            i=j;
        }
    }
    
    int max=0;
    
    string res;
    
    for(auto x :has){
     
        
        if(x.second>max){
     
            
            max=x.second;
            
            res=x.first;
        }
    }
    
    
    cout<<res<<" "<<max;
    
}

1061.约会

字符串处理(一)_第8张图片

  • 又臭又长…没意思
#include
#include

using namespace std;

int main(){
     
    
    string has[7]={
     "MON","TUE","WED","THU","FRI","SAT","SUN"};
    
    string time[14]={
     "10","11","12","13","14","15","16","17","18","19","20","21","22","23"};
        
    string s1,s2,c1,c2;
    
    cin>>s1>>s2>>c1>>c2;
    
    int len=s1.size();
    
    int len2=c1.size();
    
    bool flag =false;
    
    for(int i=0;i<len;i++){
     
        
        if(flag && (s1[i]>='0'&& s1[i]<='9' || s1[i]>='A'&&s1[i]<='N') && s1[i]==s2[i]){
     
            
            if(s1[i]>='0'&&s1[i]<='9')cout<<0<<s1[i]<<":";
                
            else cout<<time[s1[i]-'A']<<":";
                
            break;    
        }
        
        if(!flag && s1[i]>='A'&&s1[i]<='G' &&s1[i]==s2[i]){
     
            
            cout<<has[s1[i]-'A']<<" ";
            
            flag =true;
        }
        
     }
    
    for(int i =0;i<len2;i++){
     
        
        if(c1[i]>='A'&& (c1[i]<='Z' ||c1[i]>='a'&& c1[i]<='z') &&c1[i]==c2[i]){
     
            
            if(i<10)cout<<'0'<<i;
            
            else cout<<i;
            
            break;
        }
    }

}

  • yxc的

#include 
#include 

using namespace std;

int main()
{
     
    string a, b, c, d;
    cin >> a >> b >> c >> d;

    int k = 0;
    while (true)
    {
     
        if (a[k] == b[k] && a[k] >= 'A' && a[k] <= 'G') break;
        k ++ ;
    }

    char weekdays[7][4] = {
     "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};
    printf("%s ", weekdays[a[k] - 'A']);

    k ++ ;
    while (true)
    {
     
        if (a[k] == b[k] && (a[k] >= '0' && a[k] <= '9' || a[k] >= 'A' && a[k] <= 'N')) break;
        k ++ ;
    }

    printf("%02d:", a[k] <= '9' ? a[k] - '0' : a[k] - 'A' + 10);

    for (int i = 0;; i ++ )
        if (c[i] == d[i] && (c[i] >= 'a' && c[i] <= 'z' || c[i] >= 'A' && c[i] <= 'Z'))
        {
     
            printf("%02d\n", i);     //保留两位字符
            break;
        }

    return 0;
}

作者:yxc
链接:https://www.acwing.com/activity/content/code/content/262678/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1016.电话账单 **(结构体排序)

字符串处理(一)_第9张图片

  • 这题英文版是真的看不懂…
  • 简而言之就是算话费,输出每个人的通话时长,其通话时长先按照时间排序然后每个online和offline配对之后就是打通和挂断的时间,其中多余的online和offline删除
  • 计算话费:按照第一行的24小时段的话费计算,单位是美分/分钟
  • 本题的难点在于数据的存储以及话费的计算
  • 由于每一个用户个人信息较多并且会考虑到时间排序,并且最后要按找字典序名称输出
    自然想到用map存储客户姓名以及结构体存储对应数据,并且增加结构体内部排序,(为了方便对时间的排序及操作,直接改用相对于该月1号0:0点的时间存储时间)
  • 话费的计算:
  • 考虑到24个小时每个时间段话费均不同,不可能逐个计算话费,所以提前处理出前缀和数组
#include
#include
#include
#include
#include

using namespace std;

const int N=1010,M=31*24*60+10;

int n;
    
int cost[24];          //各个时段的话费

double sum[M];         //  预处理出的话费

struct record{
     
    
    int minutes;            //时间字符串对应月初的分钟数
    
    string state;           //online/offline
    
    string format_time;     //时间字符串的原格式
    
    bool operator < (const record &t)const {
     
        
        return  minutes<t.minutes;
    }
};

map<string,vector<record>> has;            //存储所有数据,按照字典序存放用户

int main(){
     

    for(int i=0;i<24;i++)cin>>cost[i];

    cin>>n;                                 
    
    for(int i=1;i<M;i++)sum[i]=sum[i-1]+cost[(i-1) %1440 /60]/100.0;        //i-1对应该分钟上一时刻的话费,如第60分钟(59~60)应该对应0:00~0:59即第一时段的话费,而不是1:00~1:59时段的话费
    
    char name [25],format_time[20],state[10];                     //要读入的姓名,要存入的时间,状态
    
    int month,date,hour,minute;
    
    for(int i=0;i<n;i++){
     
        
        scanf("%s %d:%d:%d:%d %s",name,&month,&date,&hour,&minute,state);
        
        sprintf(format_time,"%02d:%02d:%02d",date,hour,minute);           //读入格式串到format_time中
        
        int minutes=(date-1)*1440+hour*60+minute;                         //计算出当前日期对应于该月一号的分钟数
        
        has[name].push_back({
     minutes,state,format_time});
    }
    
    for(auto &p: has){
                         //遍历每一个用户,加上引用防止在遍历时二次赋值
        
        auto name =p.first;
        
        auto record=p.second;
        
        int len =record.size();
        
        sort(record.begin(),record.end());  //对该用户的数据按照时间进行排序
        
        double total=0;
        
        for(int i=0;i+1<len;i++){
                //对于每一个用户,遍历他的所有通话记录
            
            auto a=record[i],b=record[i+1];
            
            if(a.state=="on-line"&& b.state=="off-line"){
        //如果当前前后online和offline匹配,则计算入总花费
                
                if(!total)printf("%s %02d\n",name.c_str(),month);   //第一次时先输出用户姓名和月份
                
                double payment=sum[b.minutes]-sum[a.minutes];
                
                cout<<a.format_time<<" "<<b.format_time<<' '<<b.minutes-a.minutes<<" "<<"$";
                
                printf("%.2lf\n",payment);
                
                total+=payment;
            }
        }
        
        if(total)printf("Total amount: $%.2lf\n",total);        //没有金额的不输出
    }
}

1017.银行排队

字符串处理(一)_第10张图片

  • 题意是统计所有被服务客户的等待时间
  • 和上一题处理时间的方式类似,唯一的不同是对于服务窗口的处理,可以看出唯一需要使用的就是当前结束时间最早的服务窗口,自然联想到可以用小根堆priority_queue处理

#include
#include
#include
#include
#include
#include

using namespace std;

const int N=1010;

map<int,int> has;             //存放到达时间以及服务时间(arrtime,protime)

int main(){
     
    
    int n,k;
    
    cin>>n>>k;
    
    int hour,minute,second,p;
    
    for(int i=0;i<n;i++){
     
        
        scanf("%d:%d:%d %d",&hour,&minute,&second,&p);
        
        int times=hour*60*60+minute*60+second;                //时间统一转化成秒,服务时间超过60应取60
        
        p=min(p,60);
        
        has[times]=p*60;
    }
    
    priority_queue<int,vector<int>,greater<int>> q;           //维护服务窗口小根堆
    
    for(int i=0;i<k;i++)q.push(8*60*60);                     //小根堆初始化为早上八点
    
    int sum=0,cnt=0;                 //统计等待时间以及被服务用户数
    
    for(auto it:has){
     
        
        int arrtime=it.first;
        
        int protime=it.second;
        
        if(arrtime>17*60*60)break;
        
        int eartime=q.top();                              //所有窗口中目前最早可以开始服务的窗口时间
        
        q.pop();
         
        int start_time=max(eartime,arrtime);              //客户开始服务的时间应从到达时间和最早窗口时间中取最大值
        
        sum+=start_time-arrtime;
        
        q.push(start_time+protime);
        
        cnt++;                                            
    }
    
    printf("%.1lf",(double)sum/cnt/60);
}

1026.乒乓球 **(结构体排序)

字符串处理(一)_第11张图片

  • 题意不做赘述,本题难点在于既有vip球桌又有vip会员,在存储数据时我们选择普通和vip分开存储,也就是分为普通会员,vip会员,普通球桌,vip球桌四种情况来存储,而从题意上来看,我们每次只会用到最早到的普通会员,vip会员以及最早空闲的普通球桌,vip球桌,所以使用四个小根堆来存储数据
  • 情况1:空余球台比人多
  • 对于来的第一对同学,如果是普通人则分普通球台,如果是vip则分VIP球台
  • 情况2:排队人比球台多
  • 对于第一个闲下来的球台,如果是普通球台,则分配给排队的第一对同学,如果是VIP球台,则分配给队伍中的vip.
#include
#include
#include
#include
#include
#include

using namespace std;

const int N=10010,M=110,INF=1000000;

int n,k,m;

struct persons{
                                       //存储玩家信息
  
  int arrtime,playtime,start_time,waitting_time;
  
  bool operator< (const persons &t)const{
             //如果开始玩的时间不同,按照开始玩的时间在前排序,否则按照到达时间在前排序
      
      if(start_time!=t.start_time)return start_time<t.start_time;
      
      else return arrtime<t.arrtime;
  }
  
  bool operator> (const persons &t)const{
             //重载大于号,服务于优先队列
      
      return arrtime>t.arrtime;
  }

};

bool is_vip_table[M];                      //存储vip球台编号
 
int table_cnt[M];                       //记录每个球台被使用的次数

vector <persons> person;                   //处理要输出的人的信息

struct tables{
     
    
  int id;
  
  int end_time;
  
  bool operator> (const tables &t)const{
         // 按照球台服务结束时间在前排序,结束时间一样则按照id排序
      
      if(end_time!=t.end_time)return end_time>t.end_time;
      
      else return id>t.id;
  }
  
};


//服务函数
void assign(priority_queue<persons,vector<persons>,greater<persons>> &ps,priority_queue<tables,vector<tables>,greater<tables>> &ts){
         //加引用符号改变原数组信息
  
    auto p=ps.top();auto t=ts.top();
    
    ps.pop(),ts.pop();
    
    p.waitting_time=round((t.end_time-p.arrtime)/60.0);    //处理该会员等待时间,需要四舍五入
    
    p.start_time=t.end_time;                              //更新玩家开始游玩时间
    
    table_cnt[t.id]++;                                   //增加该桌上游玩的次数
    
    person.push_back(p);                                 //更新信息到输出数组中
    
    ts.push({
     t.id,t.end_time+p.playtime});               //更新球桌信息
    
}

//秒数转化成字符串的时间
string get_time(int seconds){
     
    char str[20];
    
    sprintf(str,"%02d:%02d:%02d",seconds/3600,seconds%3600/60,seconds%60);
    
    return str;
}



int main(){
     
    
    //读入信息部分
    
    cin>>n;
    
    priority_queue<persons,vector<persons>,greater<persons>> normal_person;   //分别存储普通会员和VIP会员
    priority_queue<persons,vector<persons>,greater<persons>> vip_person;
    
    normal_person.push({
     INF});              //加入无用值到队列中,避免对空队列的判断
    vip_person.push({
     INF});
    
    int arrtime,hour,minute,second,playtime,is_vip;
    
    for(int i=0;i<n;i++){
     
        
        scanf("%d:%d:%d %d %d",&hour,&minute,&second,&playtime,&is_vip);
        
        arrtime=hour*3600+minute*60+second;
        
        playtime=min(playtime*60,120*60);
        
        if(is_vip) vip_person.push({
     arrtime,playtime});
        
        else normal_person.push({
     arrtime,playtime});
    }
    
    priority_queue<tables,vector<tables>,greater<tables>> normal_table;
    priority_queue<tables,vector<tables>,greater<tables>> vip_table;
    
    normal_table.push({
     -1,INF});                
    vip_table.push({
     -1,INF});
    
    cin>>k>>m;
    
    for(int i=0;i<m;i++){
     
        
        int id;
        
        cin>>id;
        
        is_vip_table[id]=true;
    }
    
    for(int i=1;i<=k;i++){
     
        
        if(is_vip_table[i])vip_table.push({
     i,8*3600});
        
        else normal_table.push({
     i,8*3600});
    }
    
    //处理数据部分
    
    while(normal_person.size()>1||vip_person.size()>1){
     
        
        auto np=normal_person.top();
        
        auto vp=vip_person.top();
        
        int arrtime=min(np.arrtime,vp.arrtime);
        
        while(normal_table.top().end_time<arrtime){
       //两重while循环是为了把第一种情况全部转化成第二种情况,即只保留等待人比球桌多的情况
            
            auto nt=normal_table.top();
            
            normal_table.pop();
            
            nt.end_time=arrtime;                      //将所有空闲桌子结束时间全部更新成第一个到达人的时间,这样不影响后续人的开始游玩时间,又转化成了排队人比桌子多的情况
            
            normal_table.push(nt);
        }
        
        while(vip_table.top().end_time<arrtime){
     
            
            auto vt=vip_table.top();
            
            vip_table.pop();
            
            vt.end_time=arrtime;
            
            vip_table.push(vt);
        }
        
        //枚举第二种情况(即人比桌子多,将空闲桌分给排队人)
        
        auto nt=normal_table.top();
        auto vt=vip_table.top();
        
        int end_time=min(nt.end_time,vt.end_time);
        
        if(end_time>=21*3600)break;                     //最早的球桌已经排出九点之外
        
        if(vp.arrtime<=end_time && end_time==vt.end_time)assign(vip_person,vip_table);  //特判:如果当前最先结束的桌子是vip球桌并且已经有vip在等候,则优先服务vip
        
        else if(np.arrtime<vp.arrtime){
                    //否则枚举普通情况:1.普通会员先到
            
            if(nt>vt)assign(normal_person,vip_table); //普通球桌先空闲
            
            else assign(normal_person,normal_table);  //vip_球桌先空闲
        }
        
        else {
     
            
            if(nt>vt)assign(vip_person,vip_table);     //普通情况2:vip会员先到,普通球桌先空闲
            
            else assign(vip_person,normal_table);     //vip球桌先空闲
        } 
    }
    
    sort(person.begin(),person.end());             //先对输出数据排序
    
    for(auto it:person){
     
        
        cout<<get_time(it.arrtime)<<" "<<get_time(it.start_time)<<" "<<it.waitting_time<<endl; 
    }
    
    cout<<table_cnt[1];                //为使得最后一个数据不带空格,调整输出方式
    
    for(int i=2;i<=k;i++)cout<<" "<<table_cnt[i];
    
    cout<<endl;
    
    return 0;
    
}

1060.他们是否相等 **

字符串处理(一)_第12张图片

  • 本题关键在于如何将两字符串转化成题目所给的形式,有很多技巧
  • 1.确定.的位置(find函数),并且根据'.'的位置确定^10的次数,例如12345.6,'.'的位置是5,则10^次数是5,如果没有’.'则在最后一位补上
  • 2.将'.'从原位置删除,在字符串前面添加新的"0.",并且删除后面所有的前导0,每删除一个0,10的次数就应当减去1
  • 3.截取有效位数,返回处理好的新的字符串作比较即可
  • 一般来说处理这种条件较多的字符串题目最有效的方法就是按照题目原意模拟处理字符串
#include
#include
#include
#include

using namespace std;

string change(string a,int n){
     
    
    int k=a.find('.');
    
    if(k==-1)a+='.',k=a.find('.');             //.不存在,在后面补上.
    
    string s=a.substr(0,k)+a.substr(k+1);      //将.从字符串中移除,得到新的字符串
    
    while(s.size() && s[0]=='0')s=s.substr(1),k--;    //删除前导0
    
    if(s.empty())k=0;                           //如果s被删空,说明原数字是0,那么规定它的10次方是0
    
    if(s.size()>n)s=s.substr(0,n);             //如果没有被删空并且有效位超出就截取有效位
    
    else s+=string(n-s.size(),'0');           //否则有效位不够就在后面补0
    
    s="0."+s+"*10^"+to_string(k);             //添加"0."和"*10^"构成新串

    
    return s;
}

int main(){
     
    
    int n;
    
    cin>>n;
    
    string a,b;
    
    cin>>a>>b;
    
    a=change(a,n);
    
    b=change(b,n);
    
    if(a==b)cout<<"YES "<<a<<endl;
    
    else cout<<"NO "<<a<<" "<<b<<endl;
    
    return 0;
}


1073.科学计数法??

字符串处理(一)_第13张图片

  • 注意这题是科学计数法表示,就不存在0.XXXX这种情况
  • 顺便吐槽一下pat甲真傻逼各种莫名其妙过不了还不让看数据
  • 题目原意是让我们把科学计数法的数字转化成正常表示的情况
  • 1.首先我们保存10次方的系数
  • 2.如果系数是负数我们转正常数时在前面添加0.并且可能补0
  • 3.如果系数是正数我们则考虑小数点的位置,如果系数大于位数则在后面补0
  • 我们统一将数字转成0.XXX的形式,然后再进行移动小数点(相当于10的次数+1),不这样做会过不了pat甲的两个数据不知道为什么
#include 

using namespace std;

int main()
{
     
    string s;
    cin >> s;

    if (s[0] == '-') cout << '-';

    int k = s.find("E");
    string a = s[1] + s.substr(3, k - 3);  //截取数字部分
    int b = stoi(s.substr(k + 1));         //转指数部分为整数
    b ++ ;         //次数加一

    if (b <= 0) a = "0." + string(-b, '0') + a;
    else if (b >= a.size()) a += string(b - a.size(), '0');
    else a = a.substr(0, b) + '.' + a.substr(b);

    cout << a << endl;

    return 0;
}

作者:yxc
链接:https://www.acwing.com/activity/content/code/content/317851/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

//按照原来数据形式进行移动小数点,补零操作,过不了pat甲的两个数据,不知道为什么
#include
#include
#include

using namespace std;

int main(){
     
    
    string s;
    
    cin>>s;
    
    if(s[0]=='-')cout<<"-";
    
    s=s.substr(1);
    
    int k=s.find('E');
    
    string a=s.substr(0,1)+s.substr(2,k-2);
    
    int e=stoi(s.substr(k+1));
    
    string res;
    
    if(e<0)res="0."+string(-e-1,'0')+a;
    
    else {
     
        
        int len =a.size();
        
        if(e>=len)res=a+string(e-len+1,'0');
        
        else res=a.substr(0,e+1)+"."+a.substr(e+1);
        
    }
    
    cout<<res;
}

1077.Kuchiguse

字符串处理(一)_第14张图片

  • 模板题,注意第一行读入完整数n之后要getchar()读入一下接下来的换行符
#include
#include

using namespace std;

const int N=110;

string s[N];

int main(){
     
    
    int n;
    
    cin>>n;
    
    getchar();         //读入换行符,否则接下来第一个字符串会读入换行符
    
    for(int i=0;i<n;i++)getline(cin,s[i]);
    
    int len=s[0].size();
    
    string res="";
    
    for(int i=1;i<=len;i++){
     
        
        string sf=s[0].substr(len-i);
        
        bool flag=true;
        
        for(int j=1;j<n;j++){
     
            
            if(s[j].size()<i || s[j].substr(s[j].size()-i)!=sf){
     
                
                flag=false;
                
                break;
            }
        }
        
        if(flag)res=sf;
    }
    
    if(res!="")cout<<res;
    
    else cout<<"nai";
}

1082.中文读数字 **

字符串处理(一)_第15张图片

  • 又没全过淦
  • 经典分小数位讨论,之前忘了哪题了,这题是四位四位拆开
  • 拆开来单独四位四位处理数据,最后整体添加"Wan,"Yi"等字符串
  • 注意抠数字出来的时候都是低位存在vector低位,高位存在vector高位,这样方便对应哈希
  • 如果低位在前的话就要判断当前数字是对应个十百千哪一位,如'100800'抠出高位是10,但低位在前不知道1对应的是千还是百还是十,并且处理整体的时候不知道10对应的是亿还是万
  • 我们处理部分的时候只需要特判"0" 的情况,如果已处理出的字符串末尾不是0(表示前面有非零数字或者ling打头)那么我们就输出"ling",并且去掉末尾多余的"ling "
//y总ac的代码
#include 
#include 

using namespace std;

string num1[] = {
     
    "ling", "yi", "er", "san", "si",
    "wu", "liu", "qi", "ba", "jiu"
};

bool check(string s)  // 判断末尾是否是 "ling "
{
     
    return s.size() >= 5 && s.substr(s.size() - 5) == "ling ";
}

string work(int n)
{
     
    vector<int> nums;
    while (n) nums.push_back(n % 10), n /= 10;

    string num2[] = {
     "", "Shi", "Bai", "Qian"};
    string res;

    for (int i = nums.size() - 1; i >= 0; i -- )
    {
     
        int t = nums[i];
        if (t) res += num1[t] + ' ';
        else if (!check(res)) res += "ling ";
        if (t && i) res += num2[i] + ' ';
    }

    if (check(res)) res = res.substr(0, res.size() - 5);

    return res;
}

int main()
{
     
    int n;
    cin >> n;

    if (!n) puts("ling");
    else
    {
     
        if (n < 0) cout << "Fu ", n = -n;

        vector<int> nums;

        string num3[] = {
     "", "Wan", "Yi"};
        while (n) nums.push_back(n % 10000), n /= 10000;

        string res;
        for (int i = nums.size() - 1; i >= 0; i -- )
        {
     
            int t = nums[i];
            if (res.size() && t < 1000) res += "ling ";
            if (t) res += work(t);
            if (t && i) res += num3[i] + ' ';
        }

        while (check(res)) res = res.substr(0, res.size() - 5);

        res.pop_back();
        cout << res << endl;
    }

    return 0;
}

作者:yxc
链接:https://www.acwing.com/activity/content/code/content/317871/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
//没有全过的代码

#include
#include
#include
#include

using namespace std;

vector<string> nums;

string has1[10]={
     "ling","yi","er","san","si","wu","liu","qi","ba","jiu"};

string has2[4]={
     "","Shi ","Bai ","Qian "};

string has3[3]={
     "","Wan ","Yi "};

bool  check(string s){
     
    
    return s.size()>=5 && s.substr(s.size()-5)=="ling ";        
}

string helper(string s){
     
    
    string res;
    
    int len=s.size();
    
    for(int i=0;i<len;i++){
     
        
        int t=s[i]-'0';
        
        if(t)res+=has1[t]+' ';       //如果当前数字不是0则加上其对应字符串
        
        else if(!check(res))res+="ling ";   //如果当前数字是0 判断前面是否为0,如果不是0就加上0
        
        if(t)res+=has2[len-i-1];
    }
    
    if(check(res))res=res.substr(0,res.size()-5);
    
    return res;
}

int main(){
     
    
    string s;
    
    cin>>s;
    
    string  res;
    
    if(!stoi(s))puts("ling");
    
    else {
     
        
        if(s[0]=='-'){
     
            
            cout<<"Fu ";
            
            s=s.substr(1);
        }
    
        int len =s.size();
    
        nums.push_back(s.substr(0,len%4));
    
        s=s.substr(len%4);
    
        len=s.size();
        
        for(int i=0;i<len;i+=4)nums.push_back(s.substr(i,4));
        
        int len_num= nums.size();


        for(int i=0;i<len_num;i++){
     
            
            int t=stoi(nums[i]);
            
            if(t)res+=helper(nums[i]);
            
            if(t)res+=has3[len_num-i-1];
            
        }
        
        if(check(res))res=res.substr(res.size()-5);
        
        res.pop_back();
        
        cout<<res;
    }
    
}


1084.坏掉的键盘

字符串处理(一)_第16张图片

  • 这题要求按照键入的顺序输出值,不能用哈希表了,普通双指针算法就行

#include
#include
#include
#include

using namespace std;

const int N=300;

bool has[N];

int main(){
     
    
    string s1,s2;
    
    cin>>s1>>s2;
    
    int len1=s1.size(),len2=s2.size();
    
    int i=0,j=0;
    
    s2+='#';        //第一个字符串没有遍历完时第二个字符串可能已经遍历完,防止数组越界为字符串2添加一个不可能出现的字符
    
    while(i<len1 || j<len2){
     
        
        if(s1[i]!=s2[j]){
     
            
            if(s1[i]>='a' &&s1[i]<='z')s1[i]-=32;
            
            if(!has[s1[i]])cout<<s1[i];
            
            has[s1[i]]=true;
            
            i++;
        }
        
        else i++,j++;
    }
}

1108.求平均值

字符串处理(一)_第17张图片

  • 本题利用了stof函数的特性,如果转成浮点数的时候不合法,则会抛出一个异常try catch
  • 如果没有抛出异常再判断是否超过1000和两位小数即可
//没有全过的代码
#include
#include
#include

using namespace std;

bool  check(char a){
     
    
    return a>='0' &&  a<='9';
}
int main(){
     
    
    int n;
    
    cin>>n;
    
    double res=0;
    
    int cnt=0;
    
    while(n--){
     
        
        string s;
        
        cin>>s;
        
        string c=s;             //保存当前字符串一个完整的副本

        if(s[0]=='-')s=s.substr(1);
        
        if(!s.size()){
               //特判字符串为空或者只有'-'的情况
            
            printf("ERROR: %s is not a legal number\n",c.c_str());
            
            continue;
        }
        
        int len=s.size();
        
        bool flag1=true;            //标记是否合法
        
        for(int i=0;i<len;i++){
         //检查是否出现数字及'.'以外的字母
            
            if(!check(s[i]) &&  s[i]!='.'){
     
                
                flag1=false;
                
                break;
            }
        }
        
        if(flag1){
                  //如果只有数字和小数点,在判断该数是否合法
            
            int k=s.find('.');                //找到小数点的位置
        
            if(k!=-1){
                               //小数
                
                int m=s.find('.',k+1);
            
                if(m==-1 && k && len-k-1<=2){
        //如果只有一个小数点并且小数点位置合理且小于1000则合法
                    
                    double x=stof(s.c_str());
                    
                    if(x>1000.0)flag1=false;
                }
                
                else flag1=false;
            }
            
            else {
                                   //整数,小于1000即合法
                
                int x=stoi(s.c_str());
                
                if(x>1000)flag1=false;
            }
        }
        
        if(flag1){
     
            
            double x=stof(c.c_str());
            
            cnt++;
            
            res+=x;
        }
        
        else printf("ERROR: %s is not a legal number\n",c.c_str());
    }
    
    if(!cnt)printf("The average of 0 numbers is Undefined");
    
    else if(cnt==1)printf("The average of 1 number is %.2lf",res);
    
    else printf("The average of %d numbers is %.2lf",cnt,res/cnt);
    
}

//利用stof特性的代码
#include
#include
#include

using namespace std;

int main(){
     
    
    int n;
    
    cin>>n;
    
    double res=0;
    
    int cnt=0;
    
    while(n--){
     
        
        string s;
        
        cin>>s;
        
        double x;
        
        bool  flag=true;
        
        try{
     
            
            size_t idx;    //标记转化出的数字长度  
            
            x=stof(s,&idx);
            
            if(idx<s.size())flag=false;
        }
        
        catch(...){
            //抓取任意错误信息
            
            flag=false;
        }
        
        if(x>1000||x<-1000)flag=false;
        
        int k=s.find('.');
            
        if(k!=-1 && s.size()-k-1>2)flag=false;
        
        if(flag)res+=x,cnt++;
        
        else printf("ERROR: %s is not a legal number\n", s.c_str());
        
    }
    
    if(!cnt)printf("The average of 0 numbers is Undefined");
    
    else if(cnt==1)printf("The average of 1 number is %.2lf",res);
    
    else printf("The average of %d numbers is %.2lf",cnt,res/cnt);
    
}

1124.微博转发抽奖

字符串处理(一)_第18张图片

#include
#include
#include
#include

using namespace std;

const int N=1010;

string c[N];

map<string,bool> has;

int main(){
     
    
    int n,m,s;
    
    cin>>n>>m>>s;
    
    for(int i=1;i<=n;i++)cin>>c[i];
    
    if(n<s){
     
        
        cout<<"Keep going...";
        
        return 0;
    }
    for(int i=s;i<=n;){
     
        
        if(!has[c[i]]){
     
            
            cout<<c[i]<<endl;
            
            has[c[i]]=true;
        }
        
        else{
     
            
            i++;
            
            continue;
            
        } 
        
        i+=m;
    }
    
    return 0;
}

1141.PAT单位排行 ** (结构体排序–多关键字比较)

字符串处理(一)_第19张图片

  • 本题需要强调的首先是结构体内部排序的书写
  • 本题对精度要求较高,为了避免出现真实的总分是124,但用浮点数存储的是123.999999999的情况,建议在将整数取整之前加上eps,比如eps可以取 10^-8
  • 出现精度问题的原因是本题在计算分数总和时按照分别计算B级分数再相加,而和先计算成绩总和再除以1.5之间就会产生误差
#include
#include
#include
#include
#include

using namespace std;

struct inform{
     
    
    string name;
    
    double score;
    
    int cnt;
    
    inform():score(0),cnt(0){
     }       //结构体默认初始化
    
    bool operator< (const inform & t)const{
     
        
        if(t.score!=score)return score>t.score;
        
        else if(t.cnt!=cnt)return cnt<t.cnt;
        
        else return name<t.name;
    }
};

int main(){
     
    
    int n;
    
    cin>>n;
    
    map<string,inform>  has;
    
    while(n--){
     
        
        string id,school;
        
        double score;
        
        cin>>id>>score>>school;
        
        for(auto & c:school)c=tolower(c);
        
        if(id[0]=='B')score/=1.5;
        
        if(id[0]=='T')score*=1.5;
        
        has[school].score+=score;
        
        has[school].cnt++;
        
        has[school].name=school;
    }
    
    vector<inform> schs;
    
    for(auto it:has){
     
        
        it.second.score=(int)(it.second.score+1e-8);
        
        schs.push_back(it.second);
    }
    
    sort(schs.begin(),schs.end());
    
    int idx=1;
    
    int len=schs.size();
    
    cout<<len<<endl;
    
    for(int i=0;i<len;i++){
     
        
        if(i && schs[i].score!=schs[i-1].score)idx=i+1;      //以第三个人来说,要么就与上一个人并列,要么就只能是第三名
        
        cout<<idx<<" "<<schs[i].name<<" "<<(int)schs[i].score<<" "<<schs[i].cnt<<endl;
    }
}

1153. 解码PAT准考证(pair排序)

字符串处理(一)_第20张图片

  • 数据范围不大可以直接暴力但是时间卡的很紧,所以一定要用print输出并且使用unordered_map哈希
  • 本题涉及到vector>的排序,注意vector优先按照pair.first从小到大排序再按照pair.second从小到大排序
    因为我们需要根据成绩从打到小排序否则按照string字典序排序,利用这个特点将成绩的int值改为负数再排序即可实现从大到小排序
//对于每个查询,循环遍历vector,超时,过了三个数据,19分  //后来取消了io不管用,又换成unordered_map才过的acw淦但是pat还是没过时间卡的比较紧


#include
#include
#include
#include
#include

using namespace std;

struct inform {
     
    
    string rank,site,date,number,id;

    int score;
    
    bool operator < (const inform &t )const {
     
        
        if(t.score!=score)return score>t.score;
        
        else return id<t.id;
    }
};

bool cmp (const pair<string,int> a,const pair<string,int> b){
     
    
    if(a.second!=b.second)return a.second>b.second;
    
    else return a.first<b.first;
}

vector<inform> stus;

int main(){
     
    
    int n,m;
    
    ios::sync_with_stdio(false);
    
    cin.tie(0);
    
    cin>>n>>m;
    
    while(n--){
     
        
        string s;
        
        int score;
        
        cin>>s>>score;
        
        string rank,site,date,number;
        
        rank=s.substr(0,1);
        
        site=s.substr(1,3);
        
        date=s.substr(4,6);
        
        number=s.substr(10);
        
        stus.push_back({
     rank,site,date,number,s,score});
    }
    
    sort(stus.begin(),stus.end());
    
    for(int i=1;i<=m;i++){
     
        
        int type;
        
        string term;
        
        cout<<"Case "<<i<<":"<<" ";
        
        cin>>type>>term;
        
        cout<<type<<" "<<term<<endl;
        
        if(type==1){
     
            
            int cnt=0;
            
            for(auto it : stus){
     
                
                if(it.rank==term){
     
                    cout<<it.id<<" "<<it.score<<endl;
                    
                    cnt++;
                }
            }
            
            if(!cnt)cout<<"NA"<<endl;
            
        }    
            
        if(type==2){
     
            
            int sum=0,cnt=0;
            
            for(auto it:stus)if(it.site==term)sum+=it.score,cnt++;
            
            if(cnt)cout<<cnt<<" "<<sum<<endl;
            
            else cout<<"NA"<<endl;
        }
        
        if(type==3){
     
            
            unordered_map<string,int> has;
            
            for(auto it:stus)if(it.date==term)has[it.site]++;
            
            int len=has.size();
            
            if(!len)cout<<"NA"<<endl;
            
            else {
     
                vector<pair<string,int>> p;
                
                for(auto it:has)p.push_back(make_pair(it.first,it.second));
                
                sort(p.begin(),p.end(),cmp);
                
                for(auto it : p)cout<<it.first<<" "<<it.second<<endl;
            }
        }
        
    }
}
//全过的代码
#include
#include
#include
#include
#include

using namespace std;

const int N=10010;

struct inform {
     
    
    string id;
    
    int score;
    
    bool operator < (const inform &t )const {
     
        
        if(t.score!=score)return score>t.score;
        
        else return id<t.id;
    }
}p[N];



int main(){
     
    
    int n,m;
    
    cin>>n>>m;
    
    for(int i=0;i<n;i++)cin>>p[i].id>>p[i].score;
    
    for(int i=1;i<=m;i++){
     
        
        string type,term;
        
        cin>>type>>term;
        
        printf("Case %d: %s %s\n",i,type.c_str(),term.c_str());
        
        if(type=="1"){
     
            
            vector<inform> person;
            
            for(int i=0;i<n;i++)if(p[i].id[0]==term[0])person.push_back(p[i]);
            
            sort(person.begin(),person.end());
            
            if(person.size())
              for(auto it:person)printf("%s %d\n",it.id.c_str(),it.score);
              
            else printf("NA\n");
        }
        
        else if(type=="2"){
     
            
            int cnt=0,res=0;
            
            for(int i=0;i<n;i++)if(p[i].id.substr(1,3)==term)res+=p[i].score,cnt++;
            
            if(!cnt)printf("NA\n");
            
            else printf("%d %d\n",cnt,res);
        }
        
        else {
     
            
            unordered_map<string,int> has;
            
            for(int i=0;i<n;i++)if(p[i].id.substr(4,6)==term)has[p[i].id.substr(1,3)]++;
            
            if(!has.size())printf("NA\n");
            
            else {
     
                
                vector<pair<int,string>> room;
                
                for(auto it:has)room.push_back({
     -it.second,it.first});
                
                sort(room.begin(),room.end());
                
                for(auto it:room)printf("%s %d\n",it.second.c_str(),-it.first);
            }
        }
    }
}

你可能感兴趣的:(PAT甲,字符串)