bluecode-2024E-数据单元的变量替换

82 阅读2分钟

时间限制:C/C++ 1000MS,其他语言 2000MS
内存限制:C/C++ 128MB,其他语言 256MB
难度:困难
分数:100 OI排行榜得分:16(0.1分数+2难度)

描述

将一个CSV格式的数据文件中,包含有单元格引用的内容替换为对应单元格内容的实际值。
comma separated values(CSV) 逗号分隔值,CSV格式的数据文件使用逗号","作为分符将各单元的内容进行分隔

输入描述

  1. 输入只有一行数据,用逗号分隔每个单元格,行尾没有逗号。最多26个单元格,对应编号A~Z.
  2. 每个单元格的内容包含字母和数字,以及使用"<>"分隔的单元格引用,例如<A>表示引用第一个单元的值.
  3. 每个单元格的内容,在替换前和替换后均不超过100个字符
  4. 引用单元格的位置不受限制,允许排在后面的单元格被排在前面的单元格引用
  5. 不存在循环引用的情况,比如下面这种场景是不存在的:
A单元格: aCde<B>8u
B单元格: kAy<A>dzqo
  1. 不存在多重引用<>的情况,一个单元格只能引用一个其他单元格。比如下面这种场景是不存在的:
A单元格:C
B单元格: kAydzqo
C单元格: y<A><B>d
D单元格: y<<A>>d

输出描述

输出所有单元格展开后的内容,单元格之间用",“分隔。处理过程中出现错误时,输出字符串”-1"表示出错。

用例输入 1 **

1,2<A>00

用例输出 1 **

1,2100

通过:83

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <regex>
#include <functional>

std::string replace_references(const std::string& input_str) {
    // 1. Split input by comma and trim whitespace
    std::vector<std::string> cells;
    std::string current;
    for (char c : input_str) {
        if (c == ',') {
            while (!current.empty() && current[0] == ' ') current.erase(0, 1);
            while (!current.empty() && current.back() == ' ') current.pop_back();
            cells.push_back(current);
            current.clear();
        } else {
            current += c;
        }
    }
    if (!current.empty()) {
        while (!current.empty() && current[0] == ' ') current.erase(0, 1);
        while (!current.empty() && current.back() == ' ') current.pop_back();
        cells.push_back(current);
    }

    // 2. Create a map to store original cell values
    std::unordered_map<char, std::string> cell_dict;
    for (size_t i = 0; i < cells.size(); ++i) {
        cell_dict['A' + i] = cells[i];
    }

    // 3. Define recursive function to resolve cell content
    std::function<std::string*(char, std::unordered_set<char>)> resolve = 
        [&](char cell_name, std::unordered_set<char> visited) -> std::string* {
        // Check for circular reference
        if (visited.count(cell_name)) {
            return nullptr;  // Return nullptr for error
        }

        // Get current cell content
        auto it = cell_dict.find(cell_name);
        std::string content = (it != cell_dict.end()) ? it->second : "";

        // If content is empty, return empty string
        if (content.empty()) {
            static std::string empty = "";
            return &empty;
        }

        // Check for reference pattern <X>
        std::regex pattern("<([A-Z])>");
        std::smatch match;
        if (std::regex_search(content, match, pattern)) {
            char ref_cell = match[1].str()[0];

            // Check if referenced cell exists
            if (cell_dict.find(ref_cell) == cell_dict.end()) {
                return nullptr;  // Referenced cell doesn't exist
            }
			
            visited.insert(cell_name);
            std::string* resolved_ref = resolve(ref_cell, visited);
            
            if(!resolved_ref){
                return nullptr;
            }
            
            content.replace(match.position(), match.length(), *resolved_ref);
        }
		
        static std::string result;
        result = content;
        return &result;
    };

    std::vector<std::string> result;
    for(int i = 0; i < cells.size(); ++i){
        char cell = 'A' + i;
        std::string* resolved_content = resolve(cell, std::unordered_set<char>());
        
        if(!resolved_content){
            return "-1";
        }
        
        result.push_back(*resolved_content);
    }
    
    std::string output;
    for(int i = 0; i < result.size(); ++i){
        output += result[i];
        if(i != result.size() -1){
            output += ",";
        }
    }
    
    return output;
}

int main() {
    std::string user_input;
    std::getline(std::cin, user_input);
    
    std::string output = replace_references(user_input);
    std::cout << output << std::endl;
    
    return 0;
}