Source code for titan_pylib.string.string_count

 1from titan_pylib.data_structures.fenwick_tree.fenwick_tree import FenwickTree
 2import string
 3
 4
[docs] 5class StringCount: 6 7 def __init__(self, s: str, is_lower: bool = True): 8 assert isinstance(s, str) 9 self.alp: str = string.ascii_lowercase if is_lower else string.ascii_uppercase 10 self.DIC: dict[str, int] = {c: i for i, c in enumerate(self.alp)} 11 self.n: int = len(s) 12 self.s: list[str] = list(s) 13 dat: list[list[int]] = [[0] * self.n for _ in range(26)] 14 for i, c in enumerate(s): 15 dat[self.DIC[c]][i] += 1 16 self.data: list[FenwickTree] = [FenwickTree(d) for d in dat] 17
[docs] 18 def is_ascending(self, l: int, r: int) -> bool: 19 """区間[l, r)が昇順かどうか判定する / O(σlogn)""" 20 assert 0 <= l <= r <= self.n 21 end = l 22 for dat in self.data: 23 c = dat.sum(l, r) 24 end += c 25 if end > r or dat.sum(l, end) != c: 26 return False 27 return True
28
[docs] 29 def is_descending(self, l: int, r: int) -> bool: 30 """ 31 区間[l, r)が降順かどうか判定する / O(σlogn) 32 Note: 未確認 33 """ 34 assert 0 <= l <= r <= self.n 35 start = r - 1 36 for dat in reversed(self.data): 37 c = dat.sum(l, r) 38 start -= c 39 if start < l or dat.sum(start, r) != c: 40 return False 41 return True
42
[docs] 43 def get_min(self, l: int, r: int) -> str: 44 """区間[l, r)の最小の文字を返す / O(σlogn)""" 45 for i in range(26): 46 if self.data[i].sum(l, r): 47 return self.alp[i] 48 assert False, "Indexerror"
49
[docs] 50 def get_max(self, l: int, r: int) -> str: 51 """区間[l, r)の最大の文字を返す / O(σlogn)""" 52 for i in range(25, -1, -1): 53 if self.data[i].sum(l, r): 54 return self.alp[i] 55 assert False, "Indexerror"
56
[docs] 57 def __setitem__(self, k: int, c: str): 58 """k番目の文字をcに変更する / O(logn)""" 59 assert 0 <= k < self.n 60 self.data[self.DIC[self.s[k]]].add(k, -1) 61 self.s[k] = c 62 self.data[self.DIC[c]].add(k, 1)
63 64 # 区間[l, r)の全ての文字の個数を返す 65 # 返り値は要素数26のlist[int]
[docs] 66 def get_all_count(self, l: int, r: int) -> list[int]: 67 return [self.data[i].sum(l, r) for i in range(26)]
68
[docs] 69 def get_count(self, l: int, r: int, c: str) -> int: 70 """区間[l, r)のcの個数を返す / O(logn)""" 71 return self.data[self.DIC[c]].sum(l, r)
72 73 def __getitem__(self, k: int) -> str: 74 return self.s[k] 75 76 def __str__(self): 77 return "".join(self.s)