题解:P16469 [GKS 2013 #A] Read Phone Number

· · 题解

前言

本篇题解的解题方法为:模拟

题目大意

题目还是比较好理解的。

:::info[题目] 你知道如何用英文读出电话号码吗?现在让我来告诉你。

例如,在中国,电话号码是 11 位数字,如:15012233444。有人将号码划分为 3-4-4 的格式,即 150 \ 1223 \ 3444;而有人则将号码划分为 3-3-5 的格式,即 150 \ 122 \ 33444。不同的格式会导致读出这些数字的方式不同:

$150 \ 122 \ 33444$ 读作 `one five zero one double two double three triple four`。 现在问题来了: 给定一个电话号码列表以及划分格式,请输出这些号码的正确读法。 规则: 单个数字只需分开读出。 连续 $2$ 个相同数字使用 `double`。 连续 $3$ 个相同数字使用 `triple`。 连续 $4$ 个相同数字使用 `quadruple`。 连续 $5$ 个相同数字使用 `quintuple`。 连续 $6$ 个相同数字使用 `sextuple`。 连续 $7$ 个相同数字使用 `septuple`。 连续 $8$ 个相同数字使用 `octuple`。 连续 $9$ 个相同数字使用 `nonuple`。 连续 $10$ 个相同数字使用 `decuple`。 连续超过 $10$ 个相同数字则全部分开读出。 ::: ## 解题思路 根据题目要求模拟即可,没有什么思维难度,做法也比较好想。 ## 代码实现 这里有一个技巧,判断重复字符个数的时候,不用一个一个 `if`,开一个 `string` 数组 $mp$,其中, $mp_i$ 表示连续 $i$ 个相同数字使用的缩写。 同时,数字对应的英文单词也可以开一个 `string` 数组 $num$,其中 $num_i$ 表示数字 $i$ 对应的英文单词。 :::info[Code] ```cpp string num[]={"zero","one","two","three","four","five","six","seven","eight","nine"}; string mp[]={"","","double","triple","quadruple","quintuple","sextuple","septuple","octuple","nonuple","decuple"}; ``` ::: 这道题还有一个难点,就是对字符串的处理。 难点在于如何按照给定的格式对电话号码进行分组,并在每个分组内正确处理连续相同数字的读法。 输入的格式字符串如 `3-4-4`,需要将其解析为若干个数字段。这里采用的方法是在原字符串末尾加上一个 `-`,然后遍历每个字符: - 遇到数字字符时,累加到当前长度变量 $len$ 中:`len=len*10+(c-'0')`。 - 遇到 `-` 时,表示一个分组结束,此时 $len$ 的值就是该分组的长度。 ```cpp f+='-';//末尾加分号,方便处理最后一段 for(char c:f){ if(c != '-') len=len*10+(c-'0'); else{ //处理长度为 len 的分组 len=0;//一定要记得重置! } } ``` 对于每个长度为 $len$ 的分组,需要从电话号码字符串 $s$ 中取出对应的 $len$ 个字符进行处理。这里使用变量 $pos$ 记录当前处理到的位置。 在每个分组内,采用双指针的方法统计连续相同数字的个数: ```cpp for(int i=0;i<len;){ char cur=s[pos+i]; int cnt=1; //向后统计有多少个连续且相同字符 while(i+cnt<len && s[pos+i + cnt]==cur) cnt++; //根据 cnt 的值决定如何去读 i+=cnt;//跳过已经处理完的字符 } ``` 根据统计出的连续个数 $cnt$,按照题目规则输出: |$cnt$|读法| |:-:|:-:| |$1$|直接读数字| |$2 \sim 10$|使用 `double` ~ `decuple` + 数字| |$>10$|单独读出| 超过 $10$ 个相同数字全部单读,这是因为题目给出的特殊读法只支持到 `decuple`。 ### AC 代码 ```cpp #include <bits/stdc++.h> using namespace std; string num[]={"zero","one","two","three","four","five","six","seven","eight","nine"}; string mp[]={"","","double","triple","quadruple","quintuple","sextuple","septuple","octuple","nonuple","decuple"}; int main(){ int T; cin>>T; for(int t=1;t<=T;t++){ string s,f,ans; cin>>s>>f; f+='-'; int pos=0,len=0; for(char c:f){ if(c!='-') len=len*10+(c-'0'); else{ for(int i=0;i<len;){ if(pos+i>=s.size()) break; char cur=s[pos+i]; int cnt=1; while(i+cnt<len && pos+i+cnt<s.size() && s[pos+i+cnt]==cur) cnt++; if(cnt>=2 && cnt<=10){ if(!ans.empty()) ans+=" "; ans+=mp[cnt]+" "+num[cur-'0']; } else{ for(int j=0;j<cnt;j++){ if(!ans.empty()) ans+=" "; ans+=num[cur-'0']; } } i+=cnt; } pos+=len; len=0; } } cout<<"Case #"<<t<<": "<<ans<<'\n'; } return 0; } ``` [record](https://www.luogu.com.cn/record/278275210) ## 后记 这是本蒟蒻的第 $2$ 篇题解,求过。 给个赞再走呗!