1 条题解
-
0
自动搬运
来自洛谷,原作者为

Macesuted
AFOed搬运于
2025-08-24 21:37:14,当前版本为作者最后更新于2020-12-21 19:14:48,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题意
给出一段 BBCode 格式的代码,让你将其转换为 Markdown 格式。
具体语法展示在题面中,其中减少了相当多的语法,并且对输入的代码作出了一些大大减轻码量的限制。
分析
如果是让你将一个没有语法问题的 BBCode 代码转换成 Markdown 代码,相信一定不难。对于除
quote以外的指令,你可以使用直接替换的方式转换代码,如[h1]转换为#,[/b]转换为__。而quote则相对难处理,因为quote块内可能出现其他的标识符,从而影响你的解析。事实上你只需要找到[quote]出现后的第一个[/quote],然后将他们中间的部分拿出来直接作为quote块即可。那么我们考虑可能存在语法错误的情况。
- 标签匹配错误:解决标签匹配错误最常规的方法,就是开一个指令栈。每当遇到一个起始标签,就将它压入指令栈;遇到一个结束标签,就检查指令栈的栈顶是否与它对应。如果不对应,则说明出现了
Match Error情况。 - 标签未闭合:在上文指令栈的基础上,只需要在处理完整个输入之后判断一个指令栈是否不为空。如果不为空,则说明还有些标签是失配的,出现了
Unclosed Mark情况。
毕竟是大模拟,细节处还需参见代码。
代码
/** * @file P2395.cpp * @author Macesuted * @date 2020-12-21 * * @copyright Copyright (c) 2020 * */ #include <bits/stdc++.h> using namespace std; //需压入指令栈的操作的对应值 #define val_h1 1 #define val_h2 2 #define val_i 3 #define val_b 4 #define val_url 5 #define val_img 6 #define bufferSiz 1 << 16 char B[bufferSiz], *_S = B, *_T = B; #define getchar() (_S == _T && (_T = (_S = B) + fread(B, 1, bufferSiz, stdin), _S == _T) ? EOF : *_S++) string output;//输出缓存 stack<int> cmdStack;//指令栈 stack<string> infoStack;//URL信息临时存储栈 void checkStack(int val) { if(cmdStack.empty()||cmdStack.top()!=val) puts("Match Error"),exit(0);//如果栈顶标签与此标签不同 return cmdStack.pop(); } int main() { char c=getchar(); while(c!=EOF) { if(c=='[') {//开始读入标签 string cmd=""; c=getchar(); while(c!=']') cmd.push_back(c),c=getchar(); //此时已经读入完整的标签(在中括号中间的内容) bool reverse=false;//false表示起始标签,true表示结束标签 if(cmd[0]=='/') reverse=true,cmd=cmd.substr(1); if(cmd=="h1") {//直接转换 if(!reverse) output.append("# "),cmdStack.push(val_h1); else output.append(" #"),checkStack(val_h1); }else if(cmd=="h2") {//直接转换 if(!reverse) output.append("## "),cmdStack.push(val_h2); else output.append(" ##"),checkStack(val_h2); }else if(cmd=="i") {//直接转换 output.push_back('*'); if(!reverse) cmdStack.push(val_i); else checkStack(val_i); }else if(cmd=="b") {//直接转换 output.append("__"); if(!reverse) cmdStack.push(val_b); else checkStack(val_b); }else if(cmd.substr(0,3)=="url") { if(!reverse) infoStack.push(cmd.substr(4)),//由于URL信息在Markdown中后置,所以开栈临时存储 output.push_back('['),cmdStack.push(val_url); else output.append("]("+infoStack.top()+")"),infoStack.pop(),checkStack(val_url); }else if(cmd.substr(0,3)=="img") {//与上面唯一的区别就是'['的左侧多了一个'!' if(!reverse) infoStack.push(cmd.substr(4)),output.append("+")"),infoStack.pop(),checkStack(val_img); }else if(cmd=="quote") {//由于quote的特殊性,这里一次性读到quote的结束标签 char c=getchar(); while(c=='\n'||c=='\r') c=getchar();//删除quote块的头部空行 string cache="";//cache临时存储读进来的所有内容 while(c!=EOF) { cache.push_back(c); //如果cache字符串的末尾是"[/quote]",说明已结束 if(cache.size()>7&&cache.substr(cache.size()-8)=="[/quote]") break; c=getchar(); } if(c==EOF) { puts("Match Error"); return 0; }//如果读完了全文还没有读到结束标签 //比较愚笨的删除方法 cache.pop_back(),cache.pop_back(),cache.pop_back(),cache.pop_back(), cache.pop_back(),cache.pop_back(),cache.pop_back(),cache.pop_back(); while(cache.back()=='\n'||cache.back()=='\r') cache.pop_back();//删除quote块的尾部空行 if(output.back()!='\n'&&output.back()!='\r') output.push_back('\n');//quote块前需有空行 output.append("> ");//以头部符号开始 for(string::iterator i=cache.begin();i!=cache.end();i++) { output.push_back(*i); if(*i=='\n'||*i=='\r') output.append("> ");//每次换行都新增头部符号。 } output.push_back('\n');//最后需要换行 } } else output.push_back(c);//如果是常规字符,则应该输出 c=getchar(); } if(!cmdStack.empty()) { printf("Unclos"),puts("ed Mark"); return 0; }//如果指令栈没空 printf("%s\n",output.c_str());//输出缓存的输出 return 0; } - 标签匹配错误:解决标签匹配错误最常规的方法,就是开一个指令栈。每当遇到一个起始标签,就将它压入指令栈;遇到一个结束标签,就检查指令栈的栈顶是否与它对应。如果不对应,则说明出现了
- 1
信息
- ID
- 1414
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者