给你一个字符串 s ,它只包含三种字符 a, b 和 c 。
请你返回 a,b 和 c 都 至少出现过一次的子字符串数目。
示例 1:
输入:s = "abcabc"
输出:10
解释:包含 a,b 和 c 各至少一次的子字符串为 "abc", "abca", "abcab", "abcabc", "bca", "bcab", "bcabc", "cab", "cabc" 和 "abc" (相同字符串算多次)。
示例 2:
输入:s = "aaacb"
输出:3
解释:包含 a,b 和 c 各至少一次的子字符串为 "aaacb", "aacb" 和 "acb" 。
示例 3:
输入:s = "abc"
输出:1
提示:
3 <= s.length <= 5 x 10^4s只包含字符 a,b 和 c 。
分析:如果字符串的某个字串中 a,b,c 都至少出现过一次,则从这个字串开始,向右增长的子串一定全部符合题目要求。假设当前子串在原字符串 s 中出现在下标 j,i,则 j,i+1, j,i+2,······,j,s.length()-1 这些所有的字符串都符合条件,总共 length-i 个。
因此可以用双指针,j 指向当前字符串的开头,i 指向当前字符串的末尾,一个数组 cnt3 代表 a,b,c 三个字符出现的次数。当 cnt0、cnt1、cnt2 都不为空时,说明当前子串 j,i 中 a,b,c 都至少出现过一次,此时答案增加 length-i,并将 j 向右移动,直到新的字串不符合题目要求位置。这样遍历完整个字符串即可得到答案。
cpp
class Solution {
public:
int numberOfSubstrings(string s) {
int ans=0,len=s.length(),cnt[5]={0};cnt[s[0]-'a']++;
for(int i=1,j=0;s[i];++i)
{
cnt[s[i]-'a']++;
while(i-j>=2&&cnt[0]&&cnt[1]&&cnt[2])
ans+=len-i,cnt[s[j]-'a']--,++j;
}
return ans;
}
};