P2395 BBCode 转换 Markdown 题解
CANTORSORT · · 题解
简要题意
给你一段用格式语言 BBCode 书写的代码,且只含有 一级标题、二级标题、斜体文字、粗体文字、链接、图片 和 代码段 这几种格式。要求把这一段代码转换成用 Markdown 语言书写的格式代码。
思路
模拟题。但不知道为什么我居然能联想到 这道题。
为了方便处理,最好把输出存储在一个 string 里面。
而且出题人很仁慈地用这样一个样例来提醒我们:
[h1][i]Hello World![/h1][/i] //嵌套次序错误
一下子就看出来这些命令的正确嵌套顺序与栈的存储规则 完全一样。
于是就可以用栈来存储命令信息(有一点像括号匹配)。
前面四个命令都可以用简短的几行代码来解决;但是后面三个不太好搞。
链接和图片,我们都可以用一个 string 类型的 栈 来存储网址。
为什么还要用个栈啊?
因为毒瘤的 Markdown 允许用一张图片作为超链接的文字信息,就像这样:
[](https://www.luogu.com.cn/user/387212)
可以尝试把上面这段格式代码粘贴到个人主页或云剪贴板,然后你就会发现这个很毒瘤的细节了。
最后就是代码段。
当我们检测到 [quote] 时,我们就要直接继续往下输入,用一个 string 来存属于代码段的字符,直到检测出 [/quote] 为止。
接下来有两个判断:
- 是否存在形如
[quote][/quote]的情况(就是特判中间是不是空的,样例 6 需要用到) - 在开始往输出的字符串中加入代码段时,要先判断前面有没有其他的文字,以此确定要不要换行(具体见样例 7,如果没处理好前面就会多空一行)
所有格式信息都转换完以后,我们还要判断,原先那个我们用来存储命令的栈是不是空的(如果不空,就说明要输出 Unclosed Mark)。
代码(核心)
代码中的 io.write() 是我自己定义的快写函数,改成自己喜欢的输出方式就可以了~
string Ans;
stack<int> CmdStack;
stack<string> InfoStack;
map<string,int> CmdMap;
inline void CheckStack(int val)
{
if(CmdStack.empty()||CmdStack.top()!=val)
{
Ans="Match Error";
io.write(Ans);
exit(0);
}
CmdStack.pop();
}
signed main()
{
CmdMap["h1"]=1;
CmdMap["h2"]=2;
CmdMap["i"]=3;
CmdMap["b"]=4;
CmdMap["url"]=5;
CmdMap["img"]=6;
char c=getchar();
while(~c)
{
if(c=='[')
{
string Cmd;
c=getchar();
while(c!=']')
{
Cmd+=c;
c=getchar();
}
bool tail=0;
if(Cmd[0]=='/')
{
tail=1;
Cmd=Cmd.substr(1);
}
if(Cmd=="h1")
{
if(!tail)
{
Ans+="# ",
CmdStack.push(CmdMap[Cmd]);
}
else
{
Ans+=" #";
CheckStack(CmdMap[Cmd]);
}
}
else if(Cmd=="h2")
{
if(!tail)
{
Ans+="## ";
CmdStack.push(CmdMap[Cmd]);
}
else
{
Ans+=" ##";
CheckStack(CmdMap[Cmd]);
}
}
else if(Cmd=="i")
{
Ans+='*';
if(!tail)
CmdStack.push(CmdMap[Cmd]);
else
CheckStack(CmdMap[Cmd]);
}
else if(Cmd=="b")
{
Ans+="__";
if(!tail)
CmdStack.push(CmdMap[Cmd]);
else
CheckStack(CmdMap[Cmd]);
}
else if(Cmd.substr(0,3)=="url")
{
if(!tail)
{
InfoStack.push(Cmd.substr(4));
Ans+='[';
CmdStack.push(CmdMap[Cmd.substr(0,3)]);
}
else
{
Ans+="]("+InfoStack.top()+")";
InfoStack.pop();
CheckStack(CmdMap[Cmd.substr(0,3)]);
}
}
else if(Cmd.substr(0,3)=="img")
{
if(!tail)
{
InfoStack.push(Cmd.substr(4));
Ans+="![";
CmdStack.push(CmdMap[Cmd.substr(0,3)]);
}
else
{
Ans+="]("+InfoStack.top()+")";
InfoStack.pop();
CheckStack(CmdMap[Cmd.substr(0,3)]);
}
}
else if(Cmd=="quote")
{
if(tail)
{
Ans="Match Error";
io.write(Ans);
return 0;
}
char c=getchar();
while(c=='\n'||c=='\r')
c=getchar();
string Cache;
while(c!=EOF)
{
Cache+=c;
if(Cache.length()>7&&Cache.substr(Cache.size()-8)=="[/quote]")
break;
c=getchar();
}
if(Cache.length()>8)
{
if(c==EOF)
{
Ans="Match Error";
io.write(Ans);
return 0;
}
rep(i,1,8)
Cache.pop_back();
while(Cache.back()=='\n'||Cache.back()=='\r')
Cache.pop_back();
if(Ans.length()&&Ans.back()!='\n'&&Ans.back()!='\r')
Ans+='\n';
Ans+="> ";
rep(i,0,Cache.length()-1)
{
Ans+=Cache[i];
if(Cache[i]=='\n'||Cache[i]=='\r')
Ans+="> ";
}
Ans+='\n';
}
}
}
else
Ans+=c;
c=getchar();
}
if(CmdStack.size())
{
Ans="Unclosed Mark";
io.write(Ans);
return 0;
}
io.write(Ans);
return 0;
}