Count Unique Characters of All Substrings of a Given String

Count Unique Characters of All Substrings of a Given String

Let's define a function countUniqueChars(s) that returns the number of unique characters on s .

  • For example, calling countUniqueChars(s) if s = "LEETCODE" then "L" , "T" , "C" , "O" , "D" are the unique characters since they appear only once in s , therefore countUniqueChars(s) = 5 .

Given a string s , return the sum of countUniqueChars(t) where t is a substring of s . The test cases are generated such that the answer fits in a 32-bit integer.

Notice that some substrings can be repeated so in this case you have to count the repeated ones too.

Example 1:

Input: s = "ABC"
Output: 10
Explanation: All possible substrings are: "A","B","C","AB","BC" and "ABC".
Every substring is composed with only unique letters.
Sum of lengths of all substring is 1 + 1 + 1 + 2 + 2 + 3 = 10

Example 2:

Input: s = "ABA"
Output: 8
Explanation: The same as example 1, except countUniqueChars("ABA") = 1.

Example 3:

Input: s = "LEETCODE"
Output: 92

Constraints:

$1 \leq s.length \leq {10}^{5}$
 s consists of uppercase English letters only.

 

解题思路

  这题思路没想到。容易想到的思路是枚举出每一个子串,然后对每一个子串统计各个字符出现的次数,但这样做明显会超时。关键是要想到,对于某一个字符,它只有在子串中仅出现一次时,该字符才对子串有贡献。

  因此现在的思路是,对于每个字符,看看有多少个子串是满足该字符在子串中仅出现一次。假设这个字符当前所在的位置为$c_i$,同类型字符上一次出现的位置在$c_j$,下一次出现的位置在$c_k$。那么对于$c_i$这个字符来说,有$(c_i - c_j) \times (c_k - c_i)$个子串是满足该字符在子串中仅出现一次。首先子串肯定是包含$c_i$这个位置的字符,不包含$c_j$和$c_k$这两个位置的字符。然后在子串的前半部分即$( {c_j, c_i} ]$,有$c_i - c_j$种选法,后半部分即$[ {c_i, c_k} )$,有$c_k - c_i$种选法,根据乘法原理一共有$(c_i - c_j) \times (c_k - c_i)$种选法。

  因此做法是扫描一遍字符串,存储各个字符出现的位置,然后再枚举每个字符,用上面的公式来累计答案。需要注意的一点是对于每个字符都需要在最前面加入$-1$这个下标位置和在最后加入$n$这个下标位置($n$是字符串长度,下标从$0$开始)。

  AC代码如下:

 1 class Solution {
 2 public:
 3     int uniqueLetterString(string s) {
 4         vector<int> mp[26];
 5         for (int i = 0; i < s.size(); i++) {
 6             mp[s[i] - 'A'].push_back(i);
 7         }
 8         int ret = 0;
 9         for (int i = 0; i < 26; i++) {
10             mp[i].insert(mp[i].begin(), -1);
11             mp[i].push_back(s.size());
12             for (int j = 1; j < mp[i].size() - 1; j++) {
13                 ret += (mp[i][j] - mp[i][j - 1]) * (mp[i][j + 1] - mp[i][j]);
14             }
15         }
16         return ret;
17     }
18 };

 

参考资料  

  统计子串中的唯一字符:https://leetcode.cn/problems/count-unique-characters-of-all-substrings-of-a-given-string/solution/tong-ji-zi-chuan-zhong-de-wei-yi-zi-fu-b-h9pj/

posted @ 2022-09-06 16:16  onlyblues  阅读(27)  评论(0编辑  收藏  举报
Web Analytics