題目連接:(因爲要提供我的帳號,才能進入,貼一個地址吧)https://passport.ccf.org.cn/
題目大意:
(我的感受這個題,有些地方表達不夠清晰。)ios
從前有個MarkDown渲染器。它能把我寫的亂七八糟的文本,轉化成漂漂亮亮的那種具體,怎麼轉換呢?c++
- 本題有段落和項目之分,你好比說我上邊說的這兩行廢話就是段落。 而什麼是項目呢?就是你好比本行,前邊有一個點點,這就是項目,我這個項目還沒說完,就會自動切行,你好比如今。
- 而當我先有了另外一個點點也就是另外一個項目,這兩個點點,就組成了一個項目列表,中間不須要空行分割。
當我結束了上邊的項目列表,下邊要接段落的時候,中間要空一行。數組
對於段落的處理:
1. 去掉每行行首行尾的空格。優化
2. 開始打印,當這一行夠了w個字符要換行。this
3. 碰到一個或連續的多個空行要切一個空行。spa
4. 若是換的新行,開始是空格那麼就要刪掉這些空格。code
對於項目的處理:
1. 「* 」 這個表明了一條項目的開始,也就是那個點點,碰到這個東西要開始一個新的列表。ci
2. 「 」 兩個空格表明了隸屬於這個項目的內容,也就是說,看似是輸入了兩行,實際上是連在一塊兒的。get
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; } /* 4 asjcaojca aaa a */ /* 10 CSP CSP is a real realrealrealrealreal competition. Come and join us */ /* 10 * CSP * CSP is * a real competition. * * Come! and join. *Tel: * 12345 * */ /* 4 * aaaa *bbb ccc * dd eee *ff */