python short, easy to understand
Here I use 2 maps, map1 and map2, map1 records the last index for each letter, map2 records the second last index for each letter. They are both initialized as 
Here I use 2 maps, `map1` and `map2`, `map1` records the last index for each letter, `map2` records the second last index for each letter. They are both initialized as -1(means a letter hasn\'t shown up) .\n\nThen consider about introducing a new letter, it will contribute `(i - last_ch_position)` unique chars, and also decrease `(last_ch_position - second_last_ch_position)` unique chars.\n\nTake an example: ABCBB\ni = 0, ch = A, substring = A.  A hasn\'t shown up, so cur += 1, map1:{A:0}, map2:{}\ni = 1, ch = B, substring = AB, B. B hasn\'t shown up, so cur += 2, map1: {A:0, B:1}, map2:{}\ni = 2, ch = C, substring = ABC, BC, C. cur+= 3, map1:{A:0, B:1, C:2}, map2:{}\ni = 3. ch = B, sustring = ABCB, BCB, CB, B. last_b_position = 1, so it only contributes unique char to the index after `last_b_position`, which is i-map1[B] = 2, ie CB, B. It also decreases unique char in ABCB and BCB, which is map1[B] - map2[B] = 2, so cur+= 2-2, map1:{A:0, B:3, C:2}, map2:{B:1}\ni = 4, ch = B, substring = ABCBB, BCBB, CBB, BB, B. It increase one unique char which is "B" (i-map1[B]), but decreases 2 unique chars, which are "CBB, BB" (map1[B] - map2[B]), cur += 1 - 2, map1: {A:0, B:4, C:2}, map2:{B:3}\n\n```class Solution:\n    def uniqueLetterString(self, s: str) -> int:\n        map1 = collections.defaultdict(lambda:-1)    # last index for this letter\n        map2 = collections.defaultdict(lambda:-1)   # second last index for this letter\n        cur = 0\n        res = 0\n        \n        for i, ch in enumerate(s):\n            cur += (i - map1[ch]) - (map1[ch] - map2[ch])\n            map2[ch] = map1[ch]\n            map1[ch] = i\n            res += cur\n        return res\n  ```          \n
[]