1 条题解

  • 0
    @ 2025-8-24 21:37:14

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 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 块即可。

    那么我们考虑可能存在语法错误的情况。

    1. 标签匹配错误:解决标签匹配错误最常规的方法,就是开一个指令栈。每当遇到一个起始标签,就将它压入指令栈;遇到一个结束标签,就检查指令栈的栈顶是否与它对应。如果不对应,则说明出现了 Match Error 情况。
    2. 标签未闭合:在上文指令栈的基础上,只需要在处理完整个输入之后判断一个指令栈是否不为空。如果不为空,则说明还有些标签是失配的,出现了 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("!["),cmdStack.push(val_img);
                    else output.append("]("+infoStack.top()+")"),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
    上传者