统计同构子字符串的数目

87 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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^5
  • s 由小写字符串组成

思路

可以发现,这一道题,若是直接进行计算,是不好计算的,因为其中的字串也可以自成同构字符串

子子孙孙,无穷尽也。

如何思考这个问题,那么,同构字符串的定义是所有字符串都相同的串,那么长度为k的相同字符可以构成多少个子字符串呢?

答案是 i=1ki\sum_{i=1}^k i个字符串

所以:

一个长度为 k 的字符串的子字符串的数目为 k×(k+1)2\frac{k\times(k+1)}{2} 。那么我们对于每一个组来统计其贡献的「同构子字符串」数目并求和即可。

那么,我们这题的思路就很清楚了,对于整个字符串来说,将其进行统计每一个连续的k个字符串,然后计算,得出答案。

计算1到k的和的时间复杂度为O(1)

总体时间复杂度为 O(n)O(n)

代码

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