第 405 场周赛

3210. 找出加密后的字符串

class Solution {
public:
    string getEncryptedString(string s, int k) {
        int n = s.size();
        string t = s;
        for(int i = 0; i < n ; i ++)
            t[i] = s[(i + k) % n];      
        return t;
    }
};

3211. 生成不含相邻零的二进制字符串

深搜

class Solution {
public:

    vector<string> validStrings(int n) {
        vector<string> res;
        auto dfs  = [n,&res](auto && self, string s) -> void {
            if(s.size() == n){
                res.push_back(s);
                return ;
            }
            self(self, s + "1");
            if(s.back() != '0') self(self, s + "0");
            return;
        };
        dfs(dfs, "0");
        dfs(dfs, "1");
        sort(res.begin(), res.end());
        return res;
    }
};

3212. 统计 X 和 Y 频数相等的子矩阵数量

二维前缀和

class Solution {
public:
    int numberOfSubmatrices(vector<vector<char>>& grid) {
        int n = grid.size(), m = grid[0].size();
        vector X(n, vector<int>(m));
        vector Y(n, vector<int>(m));
        for(int i = 0 ; i < n; i ++)
            for(int j = 0; j < m; j ++) {
                if(grid[i][j] == 'X') X[i][j] ++;
                else if(grid[i][j] == 'Y') Y[i][j] ++;
            }
        for(int i = 0; i < n; i ++ )
            for(int j = 0; j < m; j ++){
                if(i > 0) X[i][j] += X[i - 1][j], Y[i][j] += Y[i - 1][j];
                if(j > 0) X[i][j] += X[i][j - 1], Y[i][j] += Y[i][j - 1];
                if(i > 0 and j > 0) X[i][j] -= X[i - 1][j - 1], Y[i][j] -= Y[i - 1][j - 1];
            }
        int res = 0;
        for(int i = 0; i < n; i ++)
            for(int j = 0; j < m; j ++){
                if(X[i][j] >  0 and X[i][j] == Y[i][j]) res ++;
            }
        return res;
    }
};

3213. 最小代价构造字符串

\(f[i]\)表示长度为\(i\)的前缀构成的最小代价,枚举长度\(len\),如果存在和\([i - len + 1, i]\)子串相同的串\(words[k]\),则存在转移\(f[i] = f[i - len] + cost[k]\)

快速的查找串是否存在可以用字符串哈希实现。

\(words[i]\)长度的和不超过\(5e4\),则说明长度的种类数不操作\(\sqrt{5e4}\)。因此只枚举存在的长度即可,复杂度\(O(N\sqrt(5e4))\)

class Solution {
public:
    int minimumCost(string target, vector<string>& words, vector<int>& costs) {
        const int mod = 998244353;
        int n = target.size();
        const int base = 19260817;
        vector<int> pow_base(n + 1), pre_hash(n + 1);
        pow_base[0] = 1;
        for (int i = 1; i <= n; i++) {
            pow_base[i] = (long long)pow_base[i - 1] * base % mod;
            pre_hash[i] = ((long long)pre_hash[i - 1] * base + target[i - 1]) % mod;
        }
        auto calc_hash = [&](int l, int r) -> int { // 计算 [l, r) 哈希值
            return (pre_hash[r] - (long long)pre_hash[l] * pow_base[r - l] % mod + mod) % mod;
        };
        
        map<int, unordered_map<int,int>> min_cost;
        for(int i = 0; i < words.size(); i ++) {
            int hash_val = 0;
            for(auto c : words[i])
                hash_val = ((long long)hash_val * base % mod + c) % mod;
            int len = words[i].size();
            if(min_cost[len].count(hash_val))
                min_cost[len][hash_val] = min(min_cost[len][hash_val], costs[i]);
            else 
                min_cost[len][hash_val] = costs[i]; 
        }

        vector<int> f(n + 1, INT_MAX / 2);
        f[0] = 0;
        for(int i = 1; i <= n; i ++) {
            for(const auto &[len, mc] : min_cost) {
                if(len > i) break;
                if(f[i - len] >= f[i]) continue;
                auto it = mc.find(calc_hash(i - len, i));
                if(it == mc.end()) continue;
                f[i] = min(f[i], f[i - len] + it -> second);
            }
        }
        return f[n] == INT_MAX / 2 ? - 1 : f[n];
    }
};
posted @ 2024-07-08 15:45  PHarr  阅读(10)  评论(0编辑  收藏  举报