题解:P8506 标题计数

前言

本篇题解适合刚学字符串模拟的同学阅读,语言浅显易懂。谁让作者是个蒟蒻呢。

题目分析

核心条件

  • 第一个非空格字符必须是井号 #
  • 井号后面必须紧跟着至少一个空格且不能有多个井号相连(如 ##)。
  • 在井号后面的空格后必须有长度不为 $0$ 的句子。

思路引导

提问

如何输入一行含空格的字符串?

成功

使用 string 类型自带的 getline()

提问
如何判断字符串是否为一级标题?
成功

联系我们刚分析完的核心条件,可以进行模拟。具体如下:

  • 首先,假设读入的字符串 $s$ 不是一级标题,$flag$ 为 false 。再将 $s$ 从头到尾扫一遍。

    • 如果 $s_i$ 是空格,直接跳过。
    • 否则如果 $flag$ 为 true ,说明已经满足核心条件中的 1、2 点,且现在 $s_i$ 不为空格,也满足第 3 点,计数器 $+1$。
    • 否则如果 $s_i$ 是非 # 字符,$s$ 必定不是一级标题,跳出循环。
    • 否则如果 $s_i$ 是 # 字符且满足核心条件中的 1、2 点,$flag$ 为 true 。
    • 否则 $s$ 必定不是一级标题,跳出循环。

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<bits/stdc++.h>
using namespace std;
int n,pos,cnt; // cnt用于计数符合条件的标题
bool flag; // 标记是否满足标题的前置条件
string s;
int main() {
cin>>n;
cin.ignore(); // 忽略n后面的换行符
while(n--) {
getline(cin,s); // 读取一整行文本
flag=false; // 初始化标记
for(int i=0; i<s.size(); ++i) {
if(s[i]!=' ') { // 遇到非空格字符
if(flag){ // 如果已标记为满足前置条件
cnt++; // 计数加1
break; // 跳出循环,无需继续检查
}
if(s[i]!='#') { // 非#字符,不是标题
break;
}
// 检查是否为单个#且后面跟着空格
if(s[i]=='#'&&(i==0||s[i-1]!='#')&&s[i+1]==' '&&i+1<s.size()) {
pos=i+1;
flag=true; // 标记为满足前置条件
}
if(!flag){ // 如果不满足前置条件
break; // 跳出循环
}
}
}
}
cout<<cnt; // 输出结果
return 0;
}