#CSP202006C. Markdown 渲染器
Markdown 渲染器
时间限制: 1.0 秒
空间限制: 512 MB
题目背景
Markdown 是一种轻量级的标记语言,它可以用较为简单的符号来标记文本中的成分的意义。通过套用适当的样式,即可生成一份美观的文档。Markdown 由于其轻量级的特性,深受喜爱,并在各种方面得到了广泛的运用。本题需要你解析并渲染简化的 Markdown 文档。
题目描述
本题中,你需要按照下述要求,在终端屏幕上渲染简单的 Markdown 文档。终端屏幕,可以被视为宽度为 单位,长度为无限长单位的方格,每个方格中可以被填充至多一个字符。可选地,每个方格中的字符可以带有一定的样式。在这个终端屏幕中,可以按照下列方法,渲染 Markdown 文档中的各个元素。
段落
在 Markdown 文档中,换行符将文档分为若干行。仅包含零个或多个空格的行被称为“空白行”。空白行将整个文档分割成了若干段落。例如,下面的示例文档中包含有 5 个空白行,行号分别是 2、6、7、9、10,他们将该文档分成了 3 个段落。为了能够便于你阅读,“˽”符号表示空格。“¬”符号表示换行符。
CSP¬
¬
CSP˽is¬
a˽real˽realrealrealrealreal˽¬
˽˽˽˽˽competition.¬
¬
˽˽˽¬
Come˽˽˽and˽˽˽join˽˽˽us˽˽˽¬
¬
¬
在渲染一个段落前,应该去掉每行首尾的连续空格。如果一个段落包含有多行文本,那么将各个行用一个空格连接起来,形成一个不含换行符的连续的段落文本。渲染段落时,应当首先与之前的段落或项目列表空出一行的间距,从新的一行开始连续将段落中的文本从左至右渲染在屏幕上。如果段落中的字符超出了终端的宽度,那么则应当从终端的下一行开始继续渲染其余的文本。如果余下的文本恰好是以空格字符开头,那么应该将这些连续的空格字符删除。上述文本按照这样的规则,在一个宽度为 10 的终端中渲染,其结果为:
1
+1---5----0+
1 |CSP |
2 | |
3 |CSP is a r|
4 |eal realre|
5 |alrealreal|
6 |real compe|
7 |tition. |
8 | |
9 |Come and|
10 |join us |
+----------+
项目列表
“项目”由连续的若干行文本组成,其中第一行必须以星号和空格(*˽)开头,其余的行(如果有)为以两个空格(˽˽)开头的非空白行。“项目列表”由连续的一个或多个项目组成,其中各个项目之间没有空白行或开头不是两个空格的行。如果两个项目列表之间没有空白行或开头不是两个空格的行,那么它们应当被视为一个项目列表。例如,下列文本中,行 1 、行 3-5、行 6-7、行 9 和行 10 组成了 5 个项目,它们分别属于 3 个项目列表,因为它们被空行(行 3)、段落(行 8)分隔开来。
*˽CSP¬
˽˽˽˽¬
*˽˽˽CSP˽is¬
˽˽*˽a˽real˽˽¬
˽˽˽˽˽competition.¬
*˽¬
˽˽*˽Come!˽˽˽and˽˽˽join.¬
*Tel:¬
*˽12345¬
*˽¬
在渲染一个项目列表时,应当首先与之前的段落或项目列表空出一行的间距,从新的一行开始连续渲染每个项目。在渲染一个项目前,先把这个项目的各个文本行首的两个空格字符或星号空格字符去掉。渲染时,从新的一行开始输出空格、点号、空格(˽·˽)符号,然后按照渲染一个段落的规则,渲染该项目中的各个文本行。但是,在终端上输出一个项目的随后的行时,应当插入三个空格(˽˽˽),以使这些行与第一行对齐。特别地,如果一个项目的首行除行首的星号空格字符外,没有其它的字符,那么应当直接从项目的余下的行开始渲染该项目(例如上述文本第 6 行);如果仅有一行,那么认为这个项目渲染结束(例如上述文本第 10 行)。上述文本按照该规则,在一个宽度为 10 的终端中渲染,其结果为:
1
+1---5----0+
1 | · CSP |
2 | |
3 | · CSP is |
4 | * a rea|
5 | l compe|
6 | tition.|
7 | · * Come!|
8 | and j|
9 | oin. |
10 | |
11 |*Tel: |
12 | |
13 | · 12345 |
14 | · |
+----------+
这里,原文本第 2 行是空白行,将前后两个项目分成了两个项目列表,因此在输出终端中,二者之间有空行分隔。原文本第 8 行,开头不是星号和空格,因此是一个单独的段落。
输入格式
从标准输入读入数据。
输入第一行包含一个数字 ,是终端宽度。随后从第二行开始,是被渲染的文本。
输出格式
输出到标准输出。
输出一行,是一个数字,表示渲染所需终端行数。
10
CSP
CSP is
a real realrealrealrealreal
competition.
Come and join us
10
样例1解释
该输入是本题第一个例子,渲染共需 10 行。
10
* CSP
* CSP is
* a real
competition.
*
* Come! and join.
*Tel:
* 12345
*
14
样例2解释
该输入是本题第二个例子,渲染共需 14 行。
子任务
对于 的测试点,仅包含段落,且每个段落仅包含一行文本,且每行文本长度不超过 ;
对于 的测试点,仅包含段落,且每个段落仅包含一行文本;
对于 的测试点,仅包含段落;
对于 的测试点,仅包含段落和至多一个项目列表,且输入数据大小在 2.5 MiB 以内;
对于 的测试点,包含零个或多个段落和项目列表,且 ,输入数据大小在 5 MiB 以内;
对于 的测试点,包含零个或多个段落和项目列表,,输入数据中仅包括 ASCII 字符,输入数据大小在 20 MiB 以内。
提示
本题需要你判断读取输入是否到达末尾。在 C 语言中 fgets 函数可以读取一段文本,直到换行符或给定的长度为止;feof 可以检查是否读到了文件末尾。在 C++ 中,std::istream::getline 函数可以读取一段文本,直到换行符或给定的长度为止;std::ios::eof 函数可以检查上一次读取是否因读取到了文件末尾而发生错误。在 Java 中,java.io.BufferedReader.readLine 函数可以一次读取一行文本,并在到达文件末尾的情况下返回 null。在 Python 中,io.TextIOBase.readline 函数可以一次读取一行文本,并在到达文件末尾的情况下返回空字符串。