import sequtils,algorithm template times*(n:int,body) = (for _ in 0.." ,discardable.} proc scan(): int = while true: let k = getchar_unlocked() if k < '0': return result = 10 * result + k.ord - '0'.ord type SuffixArray = ref object S : string n : int SA : seq[int] LCP : seq[int] proc SAIS(inputString:string) : seq[int] = proc SAISImpl(S:seq[int], k:int):seq[int] = # https://blog.knshnb.com/posts/sa-is/ let n = S.len # [1..255] までのbyte文字しかでないはず # 1. S, L, LMS var isS = newSeq[bool](n) isS[n-1] = true var isLMS = newSeq[bool](n) var LMSS = newSeq[int]() for i in (n-2).countdown(0): isS[i] = S[i] < S[i+1] or (S[i] == S[i+1] and isS[i + 1]) for i in 0.. 1: rank += 1 pseudoSA[orderedLMSS[1]] = rank for i in 1.. 0 and isLMS[p] : break if isDiff: rank += 1 pseudoSA[orderedLMSS[i+1]] = rank var newS = newSeq[int](LMSS.len()) index = 0 for i in 0.. 0 : var j = result.SA[B[i]-1] while j + h < n and i + h < n and S[j+h] == S[i+h]: h += 1 result.LCP[B[i]] = h if h > 0 : h -= 1 result.LCP[0] = -1 iterator find(self:SuffixArray,target:string): int = var a = -1 var b = self.n + 1 while a + 1 < b: let m = (a + b) shr 1 let start = self.SA[m] if cmp(self.S[start..= target.len: yield start else: break elif cmp(self.S[start..