题解 P5587 【打字练习】
地铁dixiatielu
2019-10-13 14:43:19
### 大模拟水题!
~~虽然调了2个半小时才调出来qwq~~
**一定要注意:数据中的范文也有退格符号!**
$getchar()$函数比$cin$和$scanf$快$qwq$所以选用$getchar()$
我并没有开二维数组存储每一行的字符串是什么,而是把所有的字符都存入了一个$char$数组。当读入换行符时,我们只需要存入'\n'即可。
最后只需要输出
$
\frac{ans}{\frac{t}{60}}
$
也就是
$
\frac{ans}{t}*60
$
即可。
代码:
```cpp
#include <cstdio>
#define reg register
using namespace std;
char s1[200007],s2[200007],ch;//s1表示范文,s2表示打字练习输入的字符
int cnt1,cnt2;
int ans;
int t;//最后读入的时间
int main()
{
s1[0] = 10;s2[0] = 10;//ASCII码的10就等于'\n'表示换行符
ch = getchar();//使用getchar加快速度
while(ch != 'F')//读到'F'的时候就是结束符EOF的最后一位了,所以应该跳出循环
{
if(ch == '<')//判断是否读入了退格符
{
if(s1[cnt1] != 10)//如果退格符前面不是换行符
{
cnt1--;//刚刚读入的字符需要删去,把当前序号--
}
ch = getchar();//重新读入一个字符
continue;//继续
}
s1[++cnt1] = ch;//如果不是换行符,那么就存入s1数组
ch = getchar();//继续读入
}
//范文读取完毕
while((ch < 'a' || ch > 'z') && ch != '.')
{
ch = getchar();
}
//为了防止读入无用字符,我们需要先把范文和实际输入之间的这些字符读取掉
while(ch != 'F')//同上,将实际输入存入s2数组
{
if(ch == '<')
{
if(s2[cnt2] != 10)
{
cnt2--;
}
ch = getchar();
continue;
}
s2[++cnt2] = ch;
ch = getchar();
}
cnt1 -= 3;
cnt2 -= 3;//由于我们刚刚读入时把"EOF"也同时存入了s1和s2数组,因此我们需要抛弃它们。所以cnt1和cnt2都要--
for(reg int i = 1,j = 1;i <= cnt1 && j <= cnt2;)//开始对比s1和s2
{
if(s1[i] == s2[j] && s1[i] != 10)//如果s1和s2的这个字母相同并且s1的这个字符不是换行符
{
ans++;//正确输入的字符数量++
}
if(s1[i] == 10)//如果范文需要换行
{
while(s2[j] != 10)//我们需要使读入的字符也跳到换行符
{
j++;
}
i++;//继续对比下一行
j++;
continue;
}
if(s2[j] == 10)//同理,读入串需要换行也要都跳到下一行
{
while(s1[i] != 10)
{
i++;
}
i++;
j++;
continue;
}
i++;
j++;
}
scanf("%d",&t);//读入耗费的时间
printf("%.0lf",(double)ans / (double)t * 60);//题目要求四舍五入,所以使用printf%.0lf这样就会自动输出四舍五入的数字
return 0;//Byebye程序 qwq
}
```