题目
题目可以在CSP官网中查看
算法思想
哈哈哈,又是一个模拟题。虽然题目看上去很长,但是只要耐下心来,一点一点将不同的内容类型区别开即可,很好理解题目的意思之后,还是可以感觉到难度不是很大的。
通过题目要求可以将输入分为三类:普通段落、项目列表项、项目列表嵌套项,这三类皆有特定的开头符号,可以根据特定的开头符号要求即可完成判断。
题目要求的整个处理过程很复杂,一遍遍历完成很容易想乱掉,所以可以把处理过程分成两部分:(1)预处理过程:这个过程中,把输入分成三类:普通段落、项目列表项、项目列表嵌套项,这个过程同时把相同段落/列表项的多行输入拼接起来,打上类别标记后存入vector管理。(2)渲染过程:这个过程中,遍历vector中存储的内容,因为预处理时已经把内容都划分好了,所以思路很清晰。段落和列表间隔时插入空行、段内/列表项内按终端每行容量处理换行即可。特别注意的就是:因为题目中没有给出输入的行数,需要自行处理。根据提示,我们用getline(cin,str)形式输入,通过检测文件末尾来跳出循环。
结果
完整代码
代码中含有较清晰的注释,按照上面两个部分:预处理过程、渲染过程一步一步即可完成该模拟题目,具体的代码如下:
#include<cstdio>
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int w;
struct Markdown
{
int type;
string s;
};
vector<Markdown>article;
bool isspace(string str)
{
int i;
for (i = 0; i < str.length(); i++)
if (str[i] != ' ') return false;
return true;
}
string stand(string str)
{
int length = str.length();
int pos1 = 0;
int pos2 = length - 1;
while (str[pos1] == ' ') pos1++;
while (str[pos2] == ' ') pos2--;
str = str.substr(pos1, pos2 - pos1 + 1);
return str;
}
int main()
{
ios::sync_with_stdio(false);
cin >> w;
string str;
while (getline(cin, str))
{
if (!isspace(str)) break; //跳过刚开始的空行
}
//项目列表
if (str.length() >= 2 && str.substr(0, 2) == "* ") //substr(0,2):截取str的前两位
{
article.push_back({ 1,stand(str.substr(2)) }); //substr(2):抛去str的前两位
}
//段落
else
{
article.push_back({ 2,stand(str) });
}
bool check = false;
while (getline(cin, str))
{
if (isspace(str))
{
check = true;
}
else
{
//上一行是空行,这一行非空,直接插入
if (check)
{
check = false;
//项目列表
if (str.length() >= 2 && str.substr(0, 2) == "* ") //substr(0,2):截取str的前两位
{
article.push_back({ 1,stand(str.substr(2)) }); //substr(2):抛去str的前两位
}
//段落
else
{
article.push_back({ 2,stand(str) });
}
}
//上一行不是空行,判断是否是同一段或者同一项目列表
else
{
Markdown& temp = article.back();
//项目列表情况
if (temp.type == 1 || temp.type == 3)
{
//项目列表项内容,直接相连
if (str.length() >= 2 && str.substr(0, 2) == " ")
temp.s = temp.s + " " + stand(str.substr(2));
//项目列表嵌套项
else if (str.length() >= 2 && str.substr(0, 2) == "* ")
article.push_back({ 3,stand(str.substr(2)) });
//新的段落
else
article.push_back({ 2,stand(str) });
}
//段落情况
else if (temp.type == 2)
{
//新开启项目列表项
if (str.length() >= 2 && str.substr(0, 2) == "* ")
{
article.push_back({ 1,stand(str.substr(2)) });
}
//本段落内容,直接连接
else
temp.s = temp.s + " " + stand(str);
}
}
}
}
long long ans = 0;
int i;
for (i = 0; i < article.size(); i++)
{
string &str = article[i].s;
//新的段落或者新的项目列表,并且不是第一个,则空一行
if (article[i].type != 3 && i > 0) ans++;
//对项目列表进行处理
if (article[i].type != 2)
{
//空项目
if (str.size() == 0)
ans++;
//不是空项目
else
{
for (int j = 0; j < str.length(); j = j + (w - 3))
{
//换行时,去掉前导空格
while (j < str.length() && str[j] == ' ')
j++;
ans++;
}
}
}
//对段落进行处理
else if(article[i].type == 2)
{
for (int j = 0; j < str.length(); j = j + w)
{
while (j < str.length() && str[j] == ' ')
j++;
ans++;
}
}
}
cout << ans << endl;
return 0;
}