3 条题解

  • 0
    @ 2026-6-9 14:13:44

    为你提供这道题的数据生成器(C++版本)。

    考虑到这道题目的特殊性(最大总长度不超过 100100,且为纯字符串模拟题),并不涉及树、图等复杂数据结构和可能导致超时的算法。因此测试点核心的区分度在于规则漏洞的拦截(边界长度、各类非法规避、特殊字符组合等)。所有生成的文件都极小(几百字节以内),非常适合OJ。

    测试点设计策略 (共10个点):

    • Test 1: 题目原样样例,测试基础通过率。
    • Test 2: 全部合规(覆盖长度6到12的不同情况),考察基础结算。
    • Test 3: 长度边界拦截(正好5个字符和13个字符,且内部字符组合全部合法),拦截没有判断长度的解法。
    • Test 4: 非法字符拦截(嵌入了空格、&*_ 等符号),拦截没有严格执行“只能由...构成”的解法。
    • Test 5: 缺失特殊字符拦截(满足长度和多类型字母数字条件,但不含!@#$)。
    • Test 6: 类别不足拦截(包含特殊字符,但大写/小写/数字只有1种)。
    • Test 7: 类别刚好满足边界(恰好2种基础字符+特殊字符,如 大+小+特、大+数+特、小+数+特),考察>=2的判定逻辑。
    • Test 8: 特殊字符位置探测(特殊字符全在开头或结尾),测试部分习惯用查找首尾判定特殊字符的错误正则表达式或错误贪心指针。
    • Test 9: 连续逗号与空串测试(类似于,,aB1!cd,,,),测试字符串分割(Split)时对空段或纯越界段的鲁棒性,避免指针异常。
    • Test 10: 综合与最大长度(接近长度 100 的混合情况),测试在复杂状态下的快速重置和连续结算。

    数据生成器 C++ 源码:

    你可以直接编译并运行以下代码,它会在同级目录下自动生成 1.in ~ 10.in 和对应的 1.out ~ 10.out 文件。

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    
    using namespace std;
    
    // 标准答案的核心校验逻辑
    bool isValid(const string& s) {
        if (s.length() < 6 || s.length() > 12) return false;
        
        bool has_lower = false;
        bool has_upper = false;
        bool has_digit = false;
        bool has_special = false;
        
        for (char c : s) {
            if (c >= 'a' && c <= 'z') has_lower = true;
            else if (c >= 'A' && c <= 'Z') has_upper = true;
            else if (c >= '0' && c <= '9') has_digit = true;
            else if (c == '!' || c == '@' || c == '#' || c == '$') has_special = true;
            else return false; // 出现非法字符,直接否决
        }
        
        int type_count = has_lower + has_upper + has_digit;
        return (type_count >= 2) && has_special;
    }
    
    // 模拟完整处理流程
    vector<string> solve(const string& input) {
        vector<string> ans;
        string current = "";
        for (char c : input) {
            if (c == ',') {
                if (isValid(current)) ans.push_back(current);
                current = "";
            } else {
                current += c;
            }
        }
        // 处理最后一段(如果没有以逗号结尾)
        if (isValid(current)) ans.push_back(current);
        return ans;
    }
    
    int main() {
        // 准备 10 个测试用例
        vector<string> test_cases(11);
        
        // 1. 原题样例
        test_cases[1] = "seHJ12!@,sjdkffH$123,sdf!@&12HDHa!,123&^YUhg@!";
        // 2. 全部合规(全类型、不同长度)
        test_cases[2] = "aB1!cd,Aa!12345678,12!@#$Aa,aB0@zX,AbCd12#";
        // 3. 长度边界测试(5位和13位,内部元素均合规,应当全部过滤)
        test_cases[3] = "aB1!c,aB1!cdefghijk,A1!ab,1234567890!@#";
        // 4. 混入非常见非法字符(空格、&、*、_、>)
        test_cases[4] = "aB1!c&,aB1!c*,aB1!c_,aB1!c~,aB1!c d,aB1!c>";
        // 5. 缺失特殊字符(完全合规的字母数字,缺了最后的灵魂)
        test_cases[5] = "aB1cde,aB1cdefghi,123456Aa,abcABC123";
        // 6. 基础字符种类不足(只有一种+特殊字符)
        test_cases[6] = "aaaaa!,AAAAAA@,123456#";
        // 7. 恰巧满足两种(大+小+特,大+数+特,小+数+特)
        test_cases[7] = "abABCD!@,ab1234!@,AB1234!@,aB1234!@";
        // 8. 极端占位(特殊字符堆砌在首尾)
        test_cases[8] = "!@#$a1,!@#$A1,aB!@#$123,1aB!@#$";
        // 9. 空串与连续逗号抵抗
        test_cases[9] = "ab12!@,,,,,AB12!@,,12!@#$,,";
        // 10. 最大复杂串(长度99,无限逼近100的要求,密集混合合规与不合规)
        test_cases[10] = "aB1!cd,xY9#ab,invalid!123456,12!A,short,verylongpassword123!,aB1!cd,xY9#ab,invalid!123,12!A,short12";
    
        // 循环生成 10 组输入输出文件
        for (int i = 1; i <= 10; ++i) {
            string in_name = to_string(i) + ".in";
            string out_name = to_string(i) + ".out";
            
            // 写入 .in 文件
            ofstream fin(in_name);
            if (!fin) {
                cerr << "无法创建文件 " << in_name << endl;
                continue;
            }
            fin << test_cases[i] << endl;
            fin.close();
            
            // 写入 .out 文件
            ofstream fout(out_name);
            if (!fout) {
                cerr << "无法创建文件 " << out_name << endl;
                continue;
            }
            vector<string> results = solve(test_cases[i]);
            for (const string& res : results) {
                fout << res << endl;
            }
            fout.close();
            
            cout << "已成功生成 Test Case " << i << " (" << in_name << ", " << out_name << ")" << endl;
        }
        
        cout << "所有数据生成完毕!" << endl;
        return 0;
    }
    

    使用方式:

    1. 将上述代码保存为 data_generator.cpp
    2. 在终端/命令行中编译:g++ data_generator.cpp -o data_generator -O2
    3. 运行:./data_generator (Windows环境下为 data_generator.exe)
    4. 运行完毕后,当前目录下会生成 1.in, 1.out ... 直至 10.in, 10.out 这 20 个文件,直接打包ZIP上传至你们的OJ即可使用。

    设计亮点提示:

    题目中限定了输入行长度不超过 100100 且用逗号分隔,对于时空复杂度本就不敏感(无论多差的解法都不会 TLE/MLE),因此生成器的重点在于“找茬”。代码完全没有使用递归栈并全部按照线性 O(N)O(N) 标准写法写就。你作为教练可以直接用 10.in 去跑部分写得冗长、逻辑分支有缺陷的学生的代码,很容易查出他们在条件判断上的 if-else 短路漏洞。

    信息

    ID
    13926
    时间
    1000ms
    内存
    128MiB
    难度
    3
    标签
    递交数
    1
    已通过
    1
    上传者