https://leetcode-cn.com/problems/number-of-substrings-containing-all-three-characters/
使用双指针,维护一个刚好满足条件的段,因为往左右扩展也会满足条件,所以扩展的数目为(左边的空余)*(右边的空余),为了避免先后出现重复,左边最多扩展到上次的左边。
class Solution {
public:
int numberOfSubstrings(string s) {
int cnts[3];
cnts[0]=cnts[1]=cnts[2]=0;
int i=0,j=0;
while(j<s.size()){
cnts[s[j]-'a']++;
if(cnts[0]>=1 && cnts[1]>=1 && cnts[2]>=1){
break;
}
j++;
}
while(cnts[s[i]-'a']>1){
cnts[s[i]-'a']--;
i++;
}
int sum=(i+1)*(s.size()-j);
int prev=i;
while(i<s.size()){
char c=s[i];
do{
cnts[s[i]-'a']--;
i++;
} while(s[i]==c && cnts[s[i]-'a']>1);
while( (cnts[0]==0 || cnts[1]==0 || cnts[2]== 0) && j+1 < s.size()){
j++;
cnts[s[j]-'a']++;
}
if(cnts[0]==0 || cnts[1]==0 || cnts[2]== 0)
break;
sum+=(i-prev)*(s.size()-j);
prev=i;
}
return sum;
}
};
这是一种固定左边,扩展右边,遍历所有位置作为左边位置的方法
class Solution {
public:
int numberOfSubstrings(string s) {
int cnts[3];
cnts[0]=cnts[1]=cnts[2]=0;
int i=0,j=-1;
int sum=0;
while(i<s.size()){
while( !(cnts[0]>=1 && cnts[1]>=1 && cnts[2]>=1)){
j++;
if(j>=s.size())
break;
cnts[s[j]-'a']++;
}
if( !(cnts[0]>=1 && cnts[1]>=1 && cnts[2]>=1))
break;
sum+=(s.size()-j);
cnts[s[i]-'a']--;
i++;
}
return sum;
}
};