来源:力扣(LeetCode)
描述:
给你一个字符串 s
,返回 s
中 同构子字符串 的数目。由于答案可能很大,只需返回对 109 + 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 <= 105
- s 由小写字符串组成
方法:数学
思路与算法
题目给出一个长度为 n 的字符串 s,并给出「同构字符串」的定义为:如果一个字符串中的所有字符都相同,那么该字符串就是同构字符串。现在我们需要求 s 中「同构子字符串」的数目。
因为「同构子字符串」为一个连续的字符序列且需要序列中的字符都相同,那么我们首先按照连续相同的字符来对字符串 ss 进行分组,比如对于字符串 “abbcccaa" 我们的分组结果为 [“a”, “bb”, “ccc”, “aa”]。因为对于一个组中字符串的任意子字符串都为「同构子字符串」,而一个长度为 m 的字符串的子字符串的数目为 m×(m+1) / 2。那么我们对于每一个组来统计其贡献的「同构子字符串」数目并求和即可。
代码:
class Solution {
public:
int countHomogenous(string s) {
long long res = 0;
long long mod = 1e9 + 7;
int prev = s[0];
int cnt = 0;
for (auto c : s) {
if (c == prev) {
cnt++;
} else {
res += (long long)(cnt + 1) * cnt / 2;
cnt = 1;
prev = c;
}
}
res += (long long)(cnt + 1) * cnt / 2;
return res % mod;
}
};
执行用时:8 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:11.4 MB, 在所有 C++ 提交中击败了47.57%的用户
复杂度分析
时间复杂度:O(n),其中 n 字符串 s 的长度。
空间复杂度:O(1)。仅使用常量空间。
author:LeetCode-Solution