开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情
统计同构子字符串的数目
给你一个字符串 s ,返回 s 中 同构子字符串 的数目。由于答案可能很大,只需返回对 10^9 + 7 取余 后的结果。
同构字符串 的定义为:如果一个字符串中的所有字符都相同,那么该字符串就是同构字符串。
子字符串 是字符串中的一个连续字符序列。
示例 1:
输入: s = "abbcccaa"
输出: 13
解释: 同构子字符串如下所列:
"a" 出现 3 次。
"aa" 出现 1 次。
"b" 出现 2 次。
"bb" 出现 1 次。
"c" 出现 3 次。
"cc" 出现 2 次。
"ccc" 出现 1 次。
3 + 1 + 2 + 1 + 3 + 2 + 1 = 13
示例 2:
输入: s = "xy"
输出: 2
解释: 同构子字符串是 "x" 和 "y" 。
示例 3:
输入: s = "zzzzz"
输出: 15
提示:
1 <= s.length <= 10^5s由小写字符串组成
思路
可以发现,这一道题,若是直接进行计算,是不好计算的,因为其中的字串也可以自成同构字符串
子子孙孙,无穷尽也。
如何思考这个问题,那么,同构字符串的定义是所有字符串都相同的串,那么长度为k的相同字符可以构成多少个子字符串呢?
答案是 个字符串
所以:
一个长度为 k 的字符串的子字符串的数目为 。那么我们对于每一个组来统计其贡献的「同构子字符串」数目并求和即可。
那么,我们这题的思路就很清楚了,对于整个字符串来说,将其进行统计每一个连续的k个字符串,然后计算,得出答案。
计算1到k的和的时间复杂度为O(1)
总体时间复杂度为
代码
class Solution {
public:
int countHomogenous(string_view s) {
char pre = s[0]; s = s.substr(1);
const int MOD = 1e9 + 7;
int cnt = 1;
int ans = 0;
for (auto& v : s) {
if (v == pre) cnt ++;
else {
ans = (ans + cnt * ((long long)cnt + 1) / 2) % MOD;
cnt = 1;
}
pre = v;
}
ans = (ans + cnt * ((long long)cnt + 1) / 2) % MOD;
return ans;
}
};