今天我们将在豆包MarsCode AI刷题平台上,完成《小C的合法k-size字符串问题》与《小U的相似字符串》这两个算法问题,通过这些练习提升用户解决此类问题的能力
《小C的合法k-size字符串问题》题面如下:
问题理解
我们需要计算长度为 n 的、仅由小写字母组成的合法的 k-size 字符串的数量。合法的 k-size 字符串是指它可以被分成恰好 k 段连续的相同字符组成的子串,并且每个连续段的长度至少为2。
数据结构选择
使用一个三维的动态规划数组 f 来存储中间结果。f[i][c][j] 表示长度为 i+1 的字符串,最后一个字符是 c,并且已经分成了 j+1 段的合法字符串的数量。
算法步骤
-
初始化:
- 对于长度为1的字符串,每个字符都可以作为初始段,因此
f[0][c][0] = 1。
- 对于长度为1的字符串,每个字符都可以作为初始段,因此
-
状态转移:
- 对于每个长度
i,遍历每个可能的最后一个字符c。 - 对于每个字符
c,遍历前一个字符prec。 - 如果
c和prec相同,说明当前字符可以继续扩展前一段,因此f[i][c][j] += f[i-1][c][j]。 - 如果
c和prec不同,并且当前段数j大于0,说明可以由前一个字符prec的段数j-1转移过来,因此f[i][c][j] += f[i-2][prec][j-1]。
- 对于每个长度
-
结果计算:
- 最终结果是所有可能的最后一个字符
c对应的f[n-2][c][k-1]的总和。
- 最终结果是所有可能的最后一个字符
具体实现
int mod = 1e9+7;
int solution(int n, int k) {
// write code here
vector<vector<vector<int>>> f(n,vector<vector<int>>(26,vector<int>(k,0)));
for(int c=0;c<26;c++){
f[0][c][0] = 1;
}
for(int i = 1;i < n;i++){
for(int c = 0;c < 26;c++){
for(int prec = 0;prec < 26;prec++){
for(int j = 0;j < k;j++){
if(c == prec){
f[i][c][j] = (f[i][c][j] + f[i-1][c][j])%mod;
} else {
if(j > 0 && i - 2 >= 0){
f[i][c][j] = (f[i][c][j] + f[i-2][prec][j-1])%mod;
}
}
}
}
}
}
int ret=0;
for(int c = 0;c < 26;c++){
ret = (ret + f[n-2][c][k-1])%mod;
}
return ret;
}
《小U的相似字符串》题面如下:
问题理解
题目要求我们判断给定的 n 个字符串中有多少对是相似的。两个字符串相似的定义是它们包含的每个字母的个数都相等。
数据结构选择
为了判断两个字符串是否相似,我们需要一种方法来表示字符串中每个字母的个数。这里使用一个长度为26的整数数组 vector<int>,其中每个位置对应一个字母,数组的值表示该字母在字符串中出现的次数。
算法步骤
-
字符串转换:
- 对于每个字符串,遍历其所有字符,并统计每个字符的出现次数,存储在
vector<int>中。
- 对于每个字符串,遍历其所有字符,并统计每个字符的出现次数,存储在
-
哈希映射:
- 为了快速比较字符串,将每个字符串的字母计数数组转换为一个哈希值。这里使用了
getHash函数,通过将字母计数数组中的每个值乘以一个基数(26)并取模(1e9+7)来生成一个唯一的哈希值。
- 为了快速比较字符串,将每个字符串的字母计数数组转换为一个哈希值。这里使用了
-
统计相似字符串对:
- 使用一个
map<ll, int>来存储每个哈希值出现的次数。 - 对于每个哈希值,如果它出现了
k次,那么可以形成k * (k - 1) / 2对相似字符串。
- 使用一个
具体实现
typedef long long ll;
int base=26, mod=1e9+7;
ll getHash(vector<int> num){
ll ret=0;
for(int i=0;i<26;i++){
ret = (ret*base + num[i])%mod;
}
return ret;
}
int solution(int n, vector<string> strings) {
// write code here
int ret=0;
map<ll,int> nums;
for(auto& s : strings){
vector<int> num(26,0);
for(char c : s){
num[c - 'a']++;
}
nums[getHash(num)]++;
}
for(auto& x : nums){
ret += x.second * (x.second - 1) / 2;
}
return ret;
}
借助豆包MarsCode AI刷题平台,我们不仅高效地解决了《小C的合法k-size字符串问题》和《小U的相似字符串》,还加深了对相关算法和数据结构的理解,后续会借助豆包MarsCode AI给大家展示更多题目的解法。