[Java/Python 3] 2 Sliding Window O(n) O(1) codes w/ explanation and analysis.
Method 1:
Maintain a sliding window (lo, hi], with lower bound exclusively and upper bound inclusively;
Traverse string s, use upper bound hi to count the numbe
**Method 1:**

1. Maintain a sliding window `(lo, hi]`, with lower bound exclusively and upper bound inclusively;
2. Traverse string `s`, use upper bound `hi` to count the number of the 3 characters, `a, b, & c`; once the sliding window includes all of the 3, we find `s.length() - hi` substrings `(lo, hi], (lo, hi + 1], ..., (lo, s.length() - 1]`;
3. Increase the lower bound `lo` by 1 (denote it as `lo'`), decrease the `count` accordingly, if the sliding window still includes all of the 3 characters, we count in substrings `(lo', hi], (lo', hi + 1], ..., (lo', s.length() - 1]`;
4. Repeat 3 till the sliding window short of at least 1 of the 3 characters, go to step 2;
5. Repeat 2 - 4 till the end of the string `s`.

```java
    public int numberOfSubstrings(String s) {
        int[] count = new int[3];
        int ans = 0;
        for (int lo = -1, hi = 0; hi < s.length(); ++hi) {
            ++count[s.charAt(hi) - 'a'];
            while (count[0] > 0 && count[1] > 0 && count[2] > 0) {
                ans += s.length() - hi; // number of valid substrings all start from lo + 1, but end at hi, hi + 1, ..., s.length() - 1, respectively.
                --count[s.charAt(++lo) - 'a'];
            }
        } 
        return ans;        
    }
```
```python
    def numberOfSubstrings(self, s: str) -> int:
        ans, lo, cnt = 0, -1, {c : 0 for c in 'abc'}
        for hi, c in enumerate(s):
            cnt[c] += 1
            while all(cnt.values()):
                ans += len(s) - hi
                lo += 1
                cnt[s[lo]] -= 1
        return ans
```


----

**Method 2: Among most recent positions of a, b, c, choose the leftmost one.**


```java
    public int numberOfSubstrings(String s) {
        int[] lastIndex = {-1, -1, -1};
        int ans = 0;
        for (int i = 0; i < s.length(); ++i) {
            lastIndex[s.charAt(i) - 'a'] = i;
            ans += 1 + Math.min(lastIndex[0], Math.min(lastIndex[1], lastIndex[2]));
        }
        return ans;
    }
```
```python
    def numberOfSubstrings(self, s: str) -> int:
        last_index, ans = [0] * 3, 0        
        for i, c in enumerate(s, 1):
            last_index[ord(c) - ord('a')] = i
            ans += min(last_index)
        return ans
```

**Analysis:**

Time: O(n), space: O(1), where n = s.length().
['String', 'Sliding Window', 'Java', 'Python3']