迭代遍历哈希表,求解《828. 统计子串中的唯一字符》
我们定义了一个函数 countUniqueChars(s) 来统计字符串 s 中的唯一字符,并返回唯一字符的个数。
例如:s = "LEETCODE" ,则其中 "L", "T","C","O","D" 都是唯一字符,因为它们只出现一次,所以 countUniqueChars(s) = 5 。
本题将会给你一个字符串 s ,我们需要返回 countUniqueChars(t) 的总和,其中 t 是 s 的子字符串。输入用例保证返回值为 32 位整数。
注意,某些子字符串可能是重复的,但你统计时也必须算上这些重复的子字符串(也就是说,你必须统计 s 的所有子字符串中的唯一字符)。
示例 1:
输入: s = "ABC"
输出: 10
解释: 所有可能的子串为:"A","B","C","AB","BC" 和 "ABC"。
其中,每一个子串都由独特字符构成。
所以其长度总和为:1 + 1 + 1 + 2 + 2 + 3 = 10
示例 2:
输入: s = "ABA"
输出: 8
解释: 除了 countUniqueChars("ABA") = 1 之外,其余与示例 1 相同。
示例 3:
输入:s = "LEETCODE"
输出:92
提示:
1 <= s.length <= 10^5
s 只包含大写英文字符
统计每个字符的贡献度:
left
rgiht
left
* right
:包含该字符串的子串区间var uniqueLetterString = function(s) {
const n = s.length, posMap = new Map
for (let i = 0; i < n; i++) {
if (posMap.has(s[i])) posMap.get(s[i]).push(i)
else posMap.set(s[i], [-1, i])
}
let r = 0
posMap.forEach(pos => {
const m = pos.length
pos.push(n)
for (let i = 1; i < m; i++) {
r += (pos[i] - pos[i - 1]) * (pos[i + 1] - pos[i])
}
})
return r
};
function uniqueLetterString(s: string): number {
const n = s.length, posMap = new Map
for (let i = 0; i < n; i++) {
if (posMap.has(s[i])) posMap.get(s[i]).push(i)
else posMap.set(s[i], [-1, i])
}
let r = 0
for (const pos of posMap.values()) {
const m = pos.length
pos.push(n)
for (let i = 1; i < m; i++) {
r += (pos[i] - pos[i - 1]) * (pos[i + 1] - pos[i])
}
}
return r
};
class Solution {
function uniqueLetterString($s) {
$n = strlen($s);
$posMap = array();
for ($i = 0; $i < $n; $i++) {
if ($posMap[$s[$i]] === null) $posMap[$s[$i]] = [-1, $i];
else $posMap[$s[$i]] []= $i;
}
$r = 0;
foreach ($posMap as $pos) {
$m = count($pos);
$pos []= $n;
for ($i = 1; $i < $m; $i++) {
$r += ($pos[$i] - $pos[$i - 1]) * ($pos[$i + 1] - $pos[$i]);
}
}
return $r;
}
}
func uniqueLetterString(s string) int {
n, posMap, r := len(s), map[rune][]int{}, 0
for i, c := range s {
if _, ok := posMap[c]; ok {
posMap[c] = append(posMap[c], i)
} else {
posMap[c] = []int{-1, i}
}
}
for _, pos := range posMap {
m := len(pos)
pos = append(pos, n)
for i := 1; i < m; i++ {
r += (pos[i] - pos[i - 1]) * (pos[i + 1] - pos[i])
}
}
return r
}
func uniqueLetterString(s string) int {
n, posMap, r := len(s), map[rune][]int{}, 0
for i, c := range s {
posMap[c] = append(posMap[c], i)
}
for _, pos := range posMap {
m := len(pos) + 1
pos = append(append([]int{-1}, pos...), n)
for i := 1; i < m; i++ {
r += (pos[i] - pos[i - 1]) * (pos[i + 1] - pos[i])
}
}
return r
}
class Solution {
public int uniqueLetterString(String s) {
int n = s.length(), r = 0;
Map<Character, List<Integer>> posMap = new HashMap<Character, List<Integer>>();
for (int i = 0; i < n; i++) {
if (posMap.containsKey(s.charAt(i))) posMap.get(s.charAt(i)).add(i);
else {
List<Integer> t = new ArrayList<Integer>();
t.add(-1);
t.add(i);
posMap.put(s.charAt(i), t);
}
}
for (List<Integer> pos : posMap.values()) {
int m = pos.size();
pos.add(n);
for (int i = 1; i < m; i++) {
r += (pos.get(i) - pos.get(i - 1)) * (pos.get(i + 1) - pos.get(i));
}
}
return r;
}
}
public class Solution {
public int UniqueLetterString(string s) {
int n = s.Length, r = 0;
Dictionary<int, IList<int>> posMap = new Dictionary<int, IList<int>>();
for (int i = 0; i < n; i++) {
if (posMap.ContainsKey(s[i])) posMap[s[i]].Add(i);
else {
IList<int> t = new List<int>();
t.Add(-1);
t.Add(i);
posMap.Add(s[i], t);
}
}
foreach (KeyValuePair<int, IList<int>> pair in posMap) {
IList<int> pos = pair.Value;
int m = pos.Count;
pos.Add(n);
for (int i = 1; i < m; i++) {
r += (pos[i] - pos[i - 1]) * (pos[i + 1] - pos[i]);
}
}
return r;
}
}
typedef struct {
int key;
int* val;
int i;
UT_hash_handle hh;
} HashItem;
int uniqueLetterString(char * s){
int n = strlen(s), r = 0;
HashItem* posMap = NULL;
for (int i = 0; i < n; i++) {
HashItem* pEntry = NULL;
int key = s[i] - '0';
HASH_FIND_INT(posMap, &key, pEntry);
if (pEntry == NULL) {
pEntry = malloc(sizeof(HashItem));
pEntry->key = s[i] - '0';
int* val = malloc(sizeof(int) * 1e5);
val[0] = -1;
val[1] = i;
pEntry->val = val;
pEntry->i = 2;
HASH_ADD_INT(posMap, key, pEntry);
} else {
(pEntry->val)[(pEntry->i)++] = i;
}
}
HashItem* tmp, *cur;
HASH_ITER(hh, posMap, cur, tmp) {
int m = cur->i;
int* pos = cur->val;
pos[m] = n;
for (int i = 1; i < m; i++) {
r += (pos[i] - pos[i - 1]) * (pos[i + 1] - pos[i]);
}
}
return r;
}
class Solution {
public:
int uniqueLetterString(string s) {
int n = s.size(), r = 0;
unordered_map<char, vector<int>> posMap;
for (int i = 0; i < n; i++) {
if (posMap.find(s[i]) == posMap.end()) posMap.emplace(s[i], vector<int>{-1, i});
else posMap[s[i]].emplace_back(i);
}
for (auto &[_, pos] : posMap) {
int m = pos.size();
pos.emplace_back(n);
for (int i = 1; i < m; i++) {
r += (pos[i] - pos[i - 1]) * (pos[i + 1] - pos[i]);
}
}
return r;
}
};
class Solution:
def uniqueLetterString(self, s: str) -> int:
n, posMap, r = len(s), dict(), 0
for i, c in enumerate(s):
if c not in posMap: posMap[c] = [-1, i]
else: posMap[c].append(i)
for pos in posMap.values():
m = len(pos)
pos.append(n)
for i in range(1, m):
r += (pos[i] - pos[i - 1]) * (pos[i + 1] - pos[i])
return r
var uniqueLetterString = function(s) {
const n = s.length, MOD = 1e8 + 9, BASE = 26, hash = new Uint32Array(n), base = new Uint32Array(n)
base[0] = 1, hash[0] = s.charCodeAt(0) - 65
for (let i = 1; i < n; i++) {
base[i] = base[i - 1] * BASE % MOD
hash[i] = (hash[i - 1] * BASE + s.charCodeAt(i) - 65) % MOD
}
let r = 0
for (let len = 1; len <= n; len++) {
const m = new Map()
for (let i = 0; i + len <= n; i++) {
const h = (hash[i + len - 1] + MOD - (i > 0 ? hash[i - 1] * base[len] : 0) % MOD) % MOD
if (m.has(h) === false) m.set(h, countUniqueChars(s, i, i + len))
r += m.get(h)
}
}
return r
};
const countUniqueChars = (s, start, end) => {
const b = new Bit, r = new Bit
for (let i = start; i < end; i++) {
const j = s.charCodeAt(i) - 65
if (b.has(j) === false) {
b.add(j)
r.add(j)
} else {
r.delete(j)
}
}
return r.size()
}
class Bit {
constructor() {
this.bit = 0
}
add(i) {
this.bit |= 1 << i
}
has(i) {
return (this.bit & 1 << i) > 0
}
delete(i) {
if (this.has(i)) this.bit ^= 1 << i
}
size() {
let r = 0, n = this.bit
while (n) {
r++
n &= n - 1
}
return r
}
}