题目链接:(由于要提供个人账号,才能进入,贴一个地址吧)https://passport.ccf.org.cn/
题目大意:
(个人感觉这个题,有些地方表达不够清晰。)
从前有个MarkDown渲染器。它能把我写的乱七八糟的文本,转化成漂漂亮亮的那种具体,怎么转换呢?
- 本题有段落和项目之分,你比如说我上边说的这两行废话就是段落。 而什么是项目呢?就是你比如本行,前边有一个点点,这就是项目,我这个项目还没说完,就会自动切行,你比如现在。
- 而当我先有了另一个点点也就是另一个项目,这两个点点,就组成了一个项目列表,中间不需要空行分割。
当我结束了上边的项目列表,下边要接段落的时候,中间要空一行。
对于段落的处理:
1. 去掉每行行首行尾的空格。
2. 开始打印,当这一行够了w个字符要换行。
3. 碰到一个或连续的多个空行要切一个空行。
4. 如果换的新行,开始是空格那么就要删掉这些空格。
对于项目的处理:
1. “* ” 这个代表了一条项目的开始,也就是那个点点,碰到这个东西要开始一个新的列表。
2. “ ” 两个空格代表了隶属于这个项目的内容,也就是说,看似是输入了两行,其实是连在一起的。
3. 渲染时吧开头的两个字符去掉,然后当段落处理。注意保持缩进。
4. 如果渲染一个项目的同时碰到了另一个项目,那么不需要换行,直接开始渲染。
5. 如果碰到了一个段落或者空行,那么要先结束当前列表的渲染,然后切个空行,再开始段落。
处理细节(坑):
1. 一上来就输入好多个空行的话要忽略,也就是说从第一个非空行开始渲染,这个题目没有说清楚。还以为要先切一下。
2. 由于时限给了1s,面对大量的string输入,很容易超时,关同步流会优化很多。
3. 当出现空项目的时候是不需要切行的,也就是说和上边的属于同一个项目列表,只不过内容是空的。
博主的实现方法核心思想就是:
1. 先判断一下本行是什么,段落还是项目
2. 再记录一下上一行是什么,项目还是段落
3. 根据两行的类别,判断需不需要切空行,需不需要添加缩进,然后去首位空格,开始添加字符。
代码:最后输出了渲染后的文本,方便读者可以进行对拍。(ans数组可以扔掉,但是为了输出结果,方便观察输出)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll MAXN = 5e5+5;
//string s[50005];
string ans[500005];
string s;
int w;
void del_sp(int tot){ // 去首尾空格
int len = s.size();
int idx1 = 1,idx2 = 0;
for(int i=0;i<len;i++){
if(s[i]!=' '){
idx1 = i;break;
}
}
for(int i=len-1;i>=0;i--){
if(s[i] != ' '){
idx2 = i;break;
}
}
string k = "";
for(int i=idx1;i<=idx2;i++){
k += s[i];
}
s = k;
}
int num = 0,all = 0;
string k = "";
void add(char c) //添加字符
{
k += c; // <--this
num++;
if(num == w){ // 1.
ans[++all] = k;
//all++;
k = "";
num = 0;
}
}
void enter(int h) //2. 切行
{
//cout<<h<<" ^ "<<endl;
if(num!=0){
ans[++all] = k;
//all++;
}
//all++;
ans[++all] = "";
k = "";
num = 0;
}
bool check_sp(int x,int idx) //判空行
{
for(int i=idx;i<s.size();i++){
if(s[i] != ' ')return false;
}
return true;
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>w;
getline(cin,s);
int fg = 0,i=0;
int flag = 0;// 0 段落 1 列表 3空行 上一行是什么
while(getline(cin,s) != NULL){
int len = s.size();
if(check_sp(i,0)){ // 空行
flag = 3;
continue;
}
if(flag == 3&&fg){
enter(i);
}
int flag2 = 0; // 本行是什么 1 列表 0 段落
if(len>=2 && s[0] == '*' && s[1] == ' '){
flag2 = 1;
s = s.substr(2,len-2);
if(flag == 1 && num!=0){
// all++;
ans[++all] = k; //3.
k = "";
num = 0;
}
if(flag == 0 ){
if(fg!=0)enter(i);
}
add('.');add('.');add('.');
}
else if(len >=2 && s[0] == ' ' && s[1] == ' '){
if(flag == 1){ // 列表
s = s.substr(2,len-2);
flag2 = 1;
if(num == 0){
add('+');add('+');add('+');
}
}
}
del_sp(i),len = s.size();
if(flag == 0){
if(flag2 == 0 && num!=0)add(' ');
}
if(flag == 1){
if(flag2 == 0){
enter(i);
}
if(flag2 == 1){
if(num>3)add(' ');
}
}
//cout<<i<<" * "<<flag<<" * "<<flag2<<endl;
for(int j=0;j<len;j++){
if(num == 0 && flag2 == 1){
add('+');add('+');add('+');
}
if(flag2 == 0){
if(num == 0 && s[j] == ' ')continue;
}
if(flag2 == 1){
if(num == 3 && s[j] == ' ')continue;
}
add(s[j]);
}
flag = flag2;
fg = 1;
}
if(num!=0){ //4.
//all++;
ans[++all] = k;
}
cout<<"------------"<<endl;
for(int i=1;i<=all;i++){
cout<<ans[i]<<endl;
}
cout<<all<<endl;
}