力扣3337. 字符串转换后的长度 II随笔
“生活并不照顾那些表现得过于疲惫的人。” ——弗里德里希·尼采
题目
给你一个由小写英文字母组成的字符串 s
,一个整数 t
表示要执行的 转换 次数,以及一个长度为 26 的数组 nums
。每次 转换 需要根据以下规则替换字符串 s
中的每个字符:
- 将
s[i]
替换为字母表中后续的nums[s[i] - 'a']
个连续字符。例如,如果s[i] = 'a'
且nums[0] = 3
,则字符'a'
转换为它后面的 3 个连续字符,结果为"bcd"
。 - 如果转换超过了
'z'
,则 回绕 到字母表的开头。例如,如果s[i] = 'y'
且nums[24] = 3
,则字符'y'
转换为它后面的 3 个连续字符,结果为"zab"
。
返回 恰好 执行 t
次转换后得到的字符串的 长度。
由于答案可能非常大,返回其对 取余的结果。
难度:困难
分析
我们可以用一个长度为26的数组存储每种字符的个数,每次操作都更改了每种字符的个数,由于此题数据量较大,暴力模拟会超时,因此我们考虑使用矩阵进行运算。我们把统计字符的数据当作一个1*n的矩阵,因为转换规则不变,所以每次操作都是乘上一个相同的n*n的矩阵,我们可以更改运算顺序,先计算n*n的矩阵的t次幂再和1*n的矩阵相乘得到结果。我们可以参照快速幂的思想实现矩阵快速幂(见代码)。
解答
class Solution {public int lengthAfterTransformations(String s, int t, List<Integer> nums) {long[] count=new long[26];final int MOD=1000000007;for (int i=0;i<s.length();i++){count[s.charAt(i)-'a']++;}long[][] matrix=new long[26][26];for (int i=0;i<26;i++){for (int j=1;j<=nums.get(i);j++){int index=(i+j)%26;matrix[i][index]=1;}}// count * matrix t次 count中的值需要MOD// matrix t次快速幂matrix = rapid(matrix,t,MOD);long[] temp=new long[26];for (int i=0;i<26;i++){for (int j=0;j<26;j++){temp[i]=(temp[i]+count[j]*matrix[j][i])%MOD;}}count=temp;long ans=0;for (int i=0;i<26;i++){ans=(ans+count[i])%MOD;}return (int)ans;}private long[][] rapid(long[][] matrix, int t, int MOD){int n=matrix.length;long[][] ans=new long[n][n];for (int i=0;i<n;i++){ans[i][i]=1;}while (t>0){if ((t&1)==1){ans=multiply(ans,matrix,MOD);}matrix=multiply(matrix,matrix,MOD);t>>=1;}return ans;}private long[][] multiply(long[][] m1, long[][] m2, int MOD){int n=m1.length;long[][] ans=new long[n][n];for (int i=0;i<n;i++){for (int j=0;j<n;j++){for (int k=0;k<n;k++){ans[i][j]=(ans[i][j]+m1[i][k]*m2[k][j])%MOD;}}}return ans;}
}
“求知若渴,虚心若愚。”——史蒂夫·乔布斯