将 s 长度为 l (0 < l < n)的 后缀字符串 删除,并将它添加在 s 的开头。 比方说,s = 'abcd' ,那么一次操作中,你可以删除后缀 'cd' ,并将它添加到 s 的开头,得到 s = 'cdab' 。
给你一个整数 k ,请你返回 恰好k 次操作将 _ _s 变为 _ _t 的方案数。
由于答案可能很大,返回答案对 109 + 7取余 后的结果。
示例 1:
**输入:** s = "abcd", t = "cdab", k = 2
**输出:** 2
**解释:**
第一种方案:
第一次操作,选择 index = 3 开始的后缀,得到 s = "dabc" 。
第二次操作,选择 index = 3 开始的后缀,得到 s = "cdab" 。
第二种方案:
第一次操作,选择 index = 1 开始的后缀,得到 s = "bcda" 。
第二次操作,选择 index = 1 开始的后缀,得到 s = "cdab" 。
示例 2:
**输入:** s = "ababab", t = "ababab", k = 1
**输出:** 2
**解释:**
第一种方案:
选择 index = 2 开始的后缀,得到 s = "ababab" 。
第二种方案:
选择 index = 4 开始的后缀,得到 s = "ababab" 。
classSolution: defnumberOfWays(self, s, t, k): n = len(s) c = self.kmp_search(s + s[:-1], t) m = [ [c - 1, c], [n - c, n - 1 - c] ] m = self.pow(m, k) return m[0][s != t]
# KMP 模板 defcalc_max_match(self, s: str) -> List[int]: match = [0] * len(s) c = 0 for i inrange(1, len(s)): v = s[i] while c and s[c] != v: c = match[c - 1] if s[c] == v: c += 1 match[i] = c returnmatch
# KMP 模板 # 返回 text 中出现了多少次 pattern(允许 pattern 重叠) defkmp_search(self, text: str, pattern: str) -> int: match = self.calc_max_match(pattern) match_cnt = c = 0 for i, v inenumerate(text): v = text[i] while c and pattern[c] != v: c = match[c - 1] if pattern[c] == v: c += 1 if c == len(pattern): match_cnt += 1 c = match[c - 1] return match_cnt
# 矩阵乘法 defmultiply(self, a: List[List[int]], b: List[List[int]]) -> List[List[int]]: c = [[0, 0], [0, 0]] for i inrange(2): for j inrange(2): c[i][j] = (a[i][0] * b[0][j] + a[i][1] * b[1][j]) % (10 ** 9 + 7) return c
# 矩阵快速幂 defpow(self, a: List[List[int]], n: int) -> List[List[int]]: res = [[1, 0], [0, 1]] while n: if n % 2: res = self.multiply(res, a) a = self.multiply(a, a) n //= 2 return res
funcnewMatrix(n, m int) matrix { a := make(matrix, n) for i := range a { a[i] = make([]int, m) } return a }
funcnewIdentityMatrix(n int) matrix { a := make(matrix, n) for i := range a { a[i] = make([]int, n) a[i][i] = 1 } return a }
func(a matrix) mul(b matrix) matrix { c := newMatrix(len(a), len(b[0])) for i, row := range a { for j := range b[0] { for k, v := range row { c[i][j] = (c[i][j] + v*b[k][j]) % mod } } } return c }
func(a matrix) pow(n int64) matrix { res := newIdentityMatrix(len(a)) for ; n > 0; n /= 2 { if n%2 > 0 { res = res.mul(a) } a = a.mul(a) } return res }
funcnumberOfWays(s, t string, k int64)int { n := len(s) calcMaxMatchLengths := func(s string) []int { match := make([]int, len(s)) for i, c := 1, 0; i < len(s); i++ { v := s[i] for c > 0 && s[c] != v { c = match[c-1] } if s[c] == v { c++ } match[i] = c } return match } kmpSearch := func(text, pattern string) (cnt int) { match := calcMaxMatchLengths(pattern) lenP := len(pattern) c := 0 for i, v := range text { for c > 0 && pattern[c] != byte(v) { c = match[c-1] } if pattern[c] == byte(v) { c++ } if c == lenP { if i-lenP+1 < n { cnt++ } c = match[c-1] } } return } c := kmpSearch(s+s, t) m := matrix{ {c - 1, c}, {n - c, n - 1 - c}, }.pow(k) if s == t { return m[0][0] } return m[0][1] }