1 条题解

  • 0
    @ 2026-5-5 17:18:17

    CF1997A Strong Password 题解

    题意

    给定一个由小写字母组成的字符串 ss,你可以在其任意位置插入一个小写字母(包括最前面和最后面),最大化新字符串的权值。输出任意一个权值最大的新字符串。

    权值定义

    • 若某个字符是第一个字符,或与前一个字符不同,贡献 22 点。
    • 若与前一个字符相同,贡献 11 点。

    分析

    设原串长为 nn,权值为 WW

    在位置 ii0in0\le i\le n,表示在 sis_i 之后,i=0i=0 表示最前)插入字符 cc

    • 插入字符 cc 的贡献:若 i=0i=0(首位)则固定 22;否则与 sis_i 比较,不同则 22,相同则 11
    • si+1s_{i+1} 的前驱由 sis_i 变为 cc,贡献可能变化。

    分类讨论权值增量 Δ\Delta

    插入位置 条件 最大 Δ\Delta
    i=0i=0i=ni=n cc 与邻位不同 +2+2
    两个不同字符之间 cc 与两者都不同
    两个相同字符之间 cc 与它们不同 +3+3

    结论:优先在相邻相同字符之间插入一个不同字符,可得 +3+3;若无相邻相同,则在首尾插入一个与邻居不同的字符,可得 +2+2。不存在更大的增量。

    构造方法

    1. 扫描 ss,找到第一个 ii 满足 si=si+1s_i = s_{i+1},在它们之间插入一个不同于 sis_i 的字符(例如 sis_i'a' 则插 'b',否则插 'a'),输出结果。
    2. 若不存在相邻相同,在 ss 开头插入一个不同于 s1s_1 的字符,输出结果。

    时间复杂度 O(s)O(|s|)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    void solve() {
        string s;
        cin >> s;
        int n = s.size();
    
        // 找相邻相同字符
        for (int i = 0; i < n - 1; ++i) {
            if (s[i] == s[i + 1]) {
                char c = (s[i] == 'a') ? 'b' : 'a';
                s.insert(s.begin() + i + 1, c);
                cout << s << '\n';
                return;
            }
        }
    
        // 无相邻相同,在开头插入不同字符
        char c = (s[0] == 'a') ? 'b' : 'a';
        cout << c << s << '\n';
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int t;
        cin >> t;
        while (t--) solve();
        return 0;
    }
    • 1

    信息

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