将 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" 。
"""DP, Z-algorithm, Fast mod.ApproachHow to represent a string?Each operation is just a rotation. Each result string can be represented by an integer from 0 to n - 1. Namely, it's just the new index of s[0].How to find the integer(s) that can represent string t?Create a new string s + t + t (length = 3 * n).Use Z-algorithm (or KMP), for each n <= index < 2 * n, calculate the maximum prefix length that each substring starts from index can match, if the length >= n, then (index - n) is a valid integer representation.How to get the result?It's a very obvious DP.If we use an integer to represent a string, we only need to consider the transition from zero to non-zero and from non-zero to zero. In other words, all the non-zero strings should have the same result.So let dp[t][i = 0/1] be the number of ways to get the zero/nonzero stringafter excatly t steps.Thendp[t][0] = dp[t - 1][1] * (n - 1).All the non zero strings can make it.dp[t][1] = dp[t - 1][0] + dp[t - 1] * (n - 2).For a particular non zero string, all the other non zero strings and zero string can make it.We have dp[0][0] = 1 and dp[0][1] = 0Use matrix multiplication.How to calculate dp[k][x = 0, 1] faster?Use matrix multiplicationvector (dp[t - 1][0], dp[t - 1][1])multiplies matrix[0 1][n - 1 n - 2]== vector (dp[t][0], dp[t - 1][1]).So we just need to calculate the kth power of the matrix which can be done by fast power algorith.ComplexityTime complexity:O(n + logk)Space complexity:O(n)"""classSolution:M:int=1000000007defadd(self,x:int,y:int)->int:x+=yifx>=self.M:x-=self.Mreturnxdefmul(self,x:int,y:int)->int:returnint(x*y%self.M)defgetZ(self,s:str)->List[int]:n=len(s)z=[0]*nleft=right=0foriinrange(1,n):ifi<=rightandz[i-left]<=right-i:z[i]=z[i-left]else:z_i=max(0,right-i+1)whilei+z_i<nands[i+z_i]==s[z_i]:z_i+=1z[i]=z_iifi+z[i]-1>right:left=iright=i+z[i]-1returnzdefmatrixMultiply(self,a:List[List[int]],b:List[List[int]])->List[List[int]]:m=len(a)n=len(a[0])p=len(b[0])r=[[0]*pfor_inrange(m)]foriinrange(m):forjinrange(p):forkinrange(n):r[i][j]=self.add(r[i][j],self.mul(a[i][k],b[k][j]))returnrdefmatrixPower(self,a:List[List[int]],y:int)->List[List[int]]:n=len(a)r=[[0]*nfor_inrange(n)]foriinrange(n):r[i][i]=1x=[a[i][:]foriinrange(n)]whiley>0:ify&1:r=self.matrixMultiply(r,x)x=self.matrixMultiply(x,x)y>>=1returnrdefnumberOfWays(self,s:str,t:str,k:int)->int:n=len(s)dp=self.matrixPower([[0,1],[n-1,n-2]],k)[0]s+=t+tz=self.getZ(s)m=n+nresult=0foriinrange(n,m):ifz[i]>=n:result=self.add(result,dp[0]ifi-n==0elsedp[1])returnresult