第 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];
}
};