# https://yukicoder.me/problems/no/430 import sequtils type PatriciaNode = ref object nexts : seq[PatriciaNode] count : int # 自身を終端とする文字列の数 countSum : int # 自身のprefixを持つ文字列の数 value : string # 念の為全部の値を持っておく.どうせ後で欲しくなるので PatriciaTree = ref object root : PatriciaNode charSize : int offset : int proc newPatriciaNode(charSize:int,value:string):PatriciaNode = new(result) result.nexts = newSeq[PatriciaNode](charSize) result.count = 1 result.countSum = 1 result.value = value proc `$`*(self:PatriciaTree):string = proc dump(node:PatriciaNode,indent:int = 0):string = if node.countSum == 0 : return "" result = "" for i in 0..= minLen: break if now.nexts[s].value[index] != S[index]: break index += 1 # 全く同じだった if S.len == index and now.nexts[s].value.len == index: now.nexts[s].count += 1 now.nexts[s].countSum += 1 return # 相手の方が短かったので相手はただの通過点であった. if now.nexts[s].value.len == index: now = now.nexts[s] continue # 異なるので中間点を作る必要がある var common = self.charSize .newPatriciaNode(if S.len == index: S else: S[0.. 0 var now = self.root var index = 0 while true: let s = S[index].ord - self.offset if now.nexts[s] == nil: return false if S.len < now.nexts[s].value.len : return false while true: if index >= now.nexts[s].value.len: break if now.nexts[s].value[index] != S[index]: break index += 1 if S.len == index and now.nexts[s].value.len == index: return now.nexts[s].count > 0 if now.nexts[s].value.len == index: now = now.nexts[s] continue return false # 追加 proc add*(self:var PatriciaTree,S:string) = if not (S in self): self.addMulti S # 構築に時間がかかるので,本当に削除はしない. # メモリが増えすぎて困る、ということがあれば削除を検討しても良い. proc delete*(self:var PatriciaTree,S:string) = if S.len == 0: if self.root.count > 0 : self.root.count -= 1 self.root.countSum -= 1 return if not (S in self): return var now = self.root var index = 0 while true: now.countSum -= 1 let s = S[index].ord - self.offset if now.nexts[s] == nil: return if S.len < now.nexts[s].value.len : return while true: if index >= now.nexts[s].value.len: break if now.nexts[s].value[index] != S[index]: break index += 1 if S.len == index and now.nexts[s].value.len == index: if now.nexts[s].count > 0: now.nexts[s].count -= 1 now.nexts[s].countSum -= 1 return if now.nexts[s].value.len == index: now = now.nexts[s] continue return # 要素数 proc len*(self:PatriciaTree):int = self.root.countSum proc countWithPrefix*(self:PatriciaTree,S:string):int = if S.len == 0: return self.root.countSum var index = 0 var now = self.root while true: if index >= S.len: return now.countSum let s = S[index].ord - self.offset if now.nexts[s] == nil: # "bcd" に "bc" みたいなノードがきた # if index == now.value.len: return now.countSum return 0 if S.len < now.nexts[s].value.len : index = now.nexts[s].value.len now = now.nexts[s] continue while true: if index >= now.nexts[s].value.len: break if now.nexts[s].value[index] != S[index]: break index += 1 now = now.nexts[s] import sequtils,algorithm,math,strutils,tables,sets template times*(n:int,body) = (for _ in 0.." ,discardable.} proc scan(): int = while true: let k = getchar_unlocked() if k < '0' or k > '9': return result = 10 * result + k.ord - '0'.ord let S = stdin.readLine() let m = scan() var T = newUpperCasePatriciaTree() for i in 0..