1 条题解

  • 0
    @ 2025-5-6 16:58:01

    解题思路分析 目标:给定一个编码序列 Cw,求有多少种方式将其分解为 Cu 和 Cv 两部分,使得解码后的序列 w=uv,且 u 和 v 都非空。 关键思路: 解码过程:模拟编码的解码过程,将每个编码对转换为对应的字符序列。 枚举分割点:尝试将编码序列 Cw 在每个可能的位置分割为 Cu 和 Cv。 验证有效性:对于每个分割点,分别解码 Cu 和 Cv,检查它们连接后是否等于原始解码序列 w。 核心挑战: 直接枚举所有可能的分割点并验证会导致时间复杂度较高。 处理回溯引用时需确保引用的子串长度不超过当前已生成的序列长度。 实现步骤 输入处理: 逐行读取输入,区分编码对类型(pi=0 为字符,pi>0 为回溯引用)。 使用字符串流处理输入中的整数和字符。 解码原始序列 w: 遍历所有编码对,生成完整的解码序列 w。 若 pi=0,直接添加字符;若 pi>0,从当前序列末尾回溯 pi 个位置并复制 ri 个字符。 枚举分割点: 遍历每个可能的分割点 i(0 ≤ i ≤ cnt-2),将编码序列分为 Cu(前 i+1 个编码对)和 Cv(剩余编码对)。 解码 Cu 和 Cv: 解码 Cu 得到序列 u。 解码 Cv 得到序列 v,注意验证回溯引用的有效性(引用长度不超过当前 v 的长度)。 验证结果: 检查 u 和 v 连接后是否等于原始序列 w,若是则计数加 1。 代码分析 输入处理函数: atoi函数将字符串转换为整数,辅助处理输入中的数字部分。 主函数流程: 读取输入:循环读取每个编码对,处理多行输入直到空行。 解码 w:遍历所有编码对,生成完整的解码序列 w。 枚举分割点:尝试每个可能的分割点,分别解码 Cu 和 Cv。 验证有效性:检查 v 的解码过程是否有效,并比较 u+v 与 w 是否相等。 关键逻辑: 回溯引用处理:在解码 v 时,确保回溯引用的长度不超过当前 v 的长度。 字符串拼接:使用append方法高效拼接子串,避免频繁创建新字符串。 复杂度分析 时间复杂度:O (N^2 * M),其中 N 是编码对的数量,M 是每次解码的平均长度。对于每个分割点,需要重新解码 v 并验证。 空间复杂度:O (M),主要用于存储解码后的字符串。 这种方法虽然直接,但由于需要多次解码和字符串操作,效率可能不高。对于大规模输入,可能需要更优化的算法,但当前代码通过枚举所有可能的分割点并验证,确保了正确性。

    #include<iostream>
    #include<sstream>
    #include<string>
    using namespace std;
    
    int op[10000][2];
    char c[10000];
    
    int atoi(string s) {
        stringstream ss;
        ss << s;
        int res;
        ss >> res;
        return res;
    }
    
    int main() {
        string s;
        int cnt = 0;
        cin >> op[cnt][0];
        if (op[cnt][0] == 0)
            cin >> c[cnt++];
        cin.get();
        while (getline(cin, s) && s != "") {
            if (s[0] == '0') {
                op[cnt][0] = 0, c[cnt++] = s[2];
                continue;
            }
            string temp;
            for (int i = 0; i < s.size(); i++) {
                if (s[i] == ' ' && temp.size() > 0)
                    op[cnt][0] = atoi(temp), temp.clear();
                else
                    temp.push_back(s[i]);
            }
            op[cnt++][1] = atoi(temp);
        }
        string w;
        for (int i = 0; i < cnt; i++) {
            if (op[i][0] == 0)
                w.push_back(c[i]);
            else {
                if (w.size() >= op[i][0]) {
                    w.append(w.substr(w.size() - op[i][0], op[i][1]));
                }
            }
        }
        int res = 0;
        for (int i = 0; i < cnt - 1; i++) {
            string u;
            for (int j = 0; j <= i; j++) {
                if (op[j][0] == 0)
                    u.push_back(c[j]);
                else {
                    if (u.size() >= op[j][0]) {
                        u.append(u.substr(u.size() - op[j][0], op[j][1]));
                    }
                }
            }
    
            string v;
            bool valid = true;
            for (int j = i + 1; j < cnt; j++) {
                if (op[j][0] == 0)
                    v.push_back(c[j]);
                else {
                    if (v.size() >= op[j][0]) {
                        v.append(v.substr(v.size() - op[j][0], op[j][1]));
                    } else {
                        valid = false;
                        break;
                    }
                }
            }
            if (valid) {
                string combined = u + v;
                if (w == combined)
                    res++;
            }
        }
        cout << res << endl;
        return 0;
    }
    • 1

    信息

    ID
    370
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者