從字符串轉換到矩陣快速冪:解決多次轉換后的長度問題

引言

在編程競賽和算法問題中,我們經常會遇到需要對字符串進行多次轉換的問題。本文將介紹一個有趣的問題:給定一個字符串和轉換規則,計算經過多次轉換后字符串的長度。由于直接模擬會導致性能問題,我們將使用矩陣快速冪來高效解決這個問題。

問題描述

給定:

  • 一個由小寫字母組成的字符串?s

  • 一個整數?t?表示轉換次數

  • 一個長度為26的數組?nums,其中?nums[i]?表示字母?'a'+i?的轉換規則

轉換規則:

  1. 將?s[i]?替換為字母表中后續的?nums[s[i]-'a']?個連續字符

  2. 如果超過?'z'?則回繞到字母表開頭

要求返回經過?t?次轉換后的字符串長度,結果對 10^9+7 取模。

示例分析

假設:

  • s = "a"

  • t = 2

  • nums = [3, 1, 1, ..., 1]?(只有第一個元素是3)

第一次轉換:

  • 'a' → 'b' + 'c' + 'd' = "bcd" (長度3)

第二次轉換:

  • 'b' → 'c' (長度1)

  • 'c' → 'd' (長度1)

  • 'd' → 'e' (長度1)
    總長度 = 1 + 1 + 1 = 3

直接模擬的局限性

直接模擬每次轉換的過程對于小的?t?是可行的,但當?t?很大時(比如 10^9),這種方法會非常低效甚至不可行,因為字符串長度會呈指數級增長。

矩陣快速冪解法

思路概述

  1. 統計字符頻率:記錄初始字符串中每個字符的出現次數

  2. 構建轉換矩陣:表示每個字符如何轉換為其他字符

  3. 矩陣快速冪:高效計算轉換矩陣的?t?次冪

  4. 計算最終長度:將初始頻率向量與轉換矩陣相乘,求和得到最終長度

詳細步驟

1. 統計字符頻率

java

long[] count = new long[26];
for (char c : s.toCharArray()) {count[c - 'a']++;
}
2. 構建轉換矩陣

對于每個字符?i,計算它轉換為其他字符的分布:

java

long[][] matrix = new long[26][26];
for (int i = 0; i < 26; i++) {int k = nums[i];int q = k / 26;  // 完整循環次數int r = k % 26;  // 剩余字符數if (r == 0) {// 均勻分布for (int j = 0; j < 26; j++) {matrix[i][j] = q % MOD;}} else {// 部分循環int start = (i + 1) % 26;int end = (i + r) % 26;for (int j = 0; j < 26; j++) {boolean inRange;if (start <= end) {inRange = (j >= start && j <= end);} else {inRange = (j >= start || j <= end);}matrix[i][j] = (q + (inRange ? 1 : 0)) % MOD;}}
}
3. 矩陣快速冪

java

private long[][] matrixPower(long[][] a, int power) {long[][] result = createIdentityMatrix();while (power > 0) {if ((power & 1) == 1) {result = multiplyMatrices(result, a);}a = multiplyMatrices(a, a);power >>= 1;}return result;
}
4. 計算最終長度

java

long[] finalCount = multiplyVectorMatrix(count, matrixPower);
long total = 0;
for (long num : finalCount) {total = (total + num) % MOD;
}
return (int) total;

復雜度分析

  • 時間復雜度:O(26^3 * log t)

    • 矩陣乘法:O(26^3)

    • 快速冪:O(log t)

  • 空間復雜度:O(26^2) 用于存儲矩陣

完整代碼實現

java

import java.util.List;class Solution {private static final int MOD = 1000000007;private static final int SIZE = 26;public int lengthAfterTransformations(String s, int t, List<Integer> nums) {int[] numsArray = new int[SIZE];for (int i = 0; i < SIZE; i++) {numsArray[i] = nums.get(i);}if (t == 0) {return s.length() % MOD;}long[] count = new long[SIZE];for (char c : s.toCharArray()) {count[c - 'a']++;}long[][] matrix = buildMatrix(numsArray);long[][] matrixPower = matrixPower(matrix, t);long[] finalCount = multiplyVectorMatrix(count, matrixPower);long total = 0;for (long num : finalCount) {total = (total + num) % MOD;}return (int) total;}private long[][] buildMatrix(int[] nums) {long[][] matrix = new long[SIZE][SIZE];for (int i = 0; i < SIZE; i++) {int k = nums[i];int q = k / 26;int r = k % 26;if (r == 0) {for (int j = 0; j < SIZE; j++) {matrix[i][j] = q % MOD;}} else {int start = (i + 1) % 26;int end = (i + r) % 26;for (int j = 0; j < SIZE; j++) {boolean inRange;if (start <= end) {inRange = (j >= start && j <= end);} else {inRange = (j >= start || j <= end);}matrix[i][j] = (q + (inRange ? 1 : 0)) % MOD;}}}return matrix;}private long[][] matrixPower(long[][] a, int power) {long[][] result = createIdentityMatrix();while (power > 0) {if ((power & 1) == 1) {result = multiplyMatrices(result, a);}a = multiplyMatrices(a, a);power >>= 1;}return result;}private long[][] createIdentityMatrix() {long[][] matrix = new long[SIZE][SIZE];for (int i = 0; i < SIZE; i++) {matrix[i][i] = 1;}return matrix;}private long[][] multiplyMatrices(long[][] a, long[][] b) {long[][] result = new long[SIZE][SIZE];for (int i = 0; i < SIZE; i++) {for (int k = 0; k < SIZE; k++) {if (a[i][k] == 0) continue;for (int j = 0; j < SIZE; j++) {result[i][j] = (result[i][j] + a[i][k] * b[k][j]) % MOD;}}}return result;}private long[] multiplyVectorMatrix(long[] vector, long[][] matrix) {long[] result = new long[SIZE];for (int j = 0; j < SIZE; j++) {for (int i = 0; i < SIZE; i++) {result[j] = (result[j] + vector[i] * matrix[i][j]) % MOD;}}return result;}
}

總結

通過這個問題,我們學習了:

  1. 如何將字符串轉換問題建模為矩陣運算

  2. 使用矩陣快速冪高效處理多次轉換

  3. 如何處理大數取模問題

這種方法不僅適用于這個問題,還可以推廣到其他類似的線性變換問題中。掌握矩陣快速冪技術對解決算法競賽中的許多問題都大有裨益。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/80951.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/80951.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/80951.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Vue2 elementUI 二次封裝命令式表單彈框組件

需求&#xff1a;封裝一個表單彈框組件&#xff0c;彈框和表單是兩個組件&#xff0c;表單組件以插槽的形式動態傳入彈框組件中。 外部組件使用的方式如下&#xff1a; 直接上代碼&#xff1a; MyDialog.vue 彈框組件 <template><el-dialog:titletitle:visible.syn…

React Hooks:從“這什么鬼“到“真香“的奇幻之旅

寫在前面:一個讓React老手都拍案叫絕的魔法 “等等,函數組件怎么能有狀態?!” —— 這是2018年我第一次聽說React Hooks時的反應。當時我正在用class組件寫一個復雜的表單,生命周期方法亂得像一碗意大利面。直到我看到了這段代碼: function Counter() {const [count, s…

論文閱讀筆記——雙流網絡

雙流網絡論文 視頻相比圖像包含更多信息&#xff1a;運動信息、時序信息、背景信息等等。 原先處理視頻的方法&#xff1a; CNN LSTM&#xff1a;CNN 抽取關鍵特征&#xff0c;LSTM 做時序邏輯&#xff1b;抽取視頻中關鍵 K 幀輸入 CNN 得到圖片特征&#xff0c;再輸入 LSTM&…

SpringBoot Vue MySQL酒店民宿預訂系統源碼(支付寶沙箱支付)+代碼講解視頻

&#x1f497;博主介紹&#x1f497;&#xff1a;?在職Java研發工程師、專注于程序設計、源碼分享、技術交流、專注于Java技術領域和畢業設計? 溫馨提示&#xff1a;文末有 CSDN 平臺官方提供的老師 Wechat / QQ 名片 :) Java精品實戰案例《700套》 2025最新畢業設計選題推薦…

右值引用的學習

傳統的C語法中就有引用的語法&#xff0c;而C11中新增了的右值引用語法特性&#xff0c;所以從現在開始我們之前學習的引用就叫做左值引用。無論左值引用還是右值引用&#xff0c;都是給對象取別名。 左值引用和右值引用 在講之前&#xff0c;我們先來看一下什么是左值和右值…

PHP黑白膠卷底片圖轉彩圖功能 V2025.05.15

關于底片轉彩圖 傳統照片底片是攝影過程中生成的反色圖像&#xff0c;為了欣賞照片&#xff0c;需要通過沖印過程將底片轉化為正像。而隨著數字技術的發展&#xff0c;我們現在可以使用數字工具不僅將底片轉為正像&#xff0c;還可以添加色彩&#xff0c;重現照片原本的色彩效…

【Three.js基礎學習】36.particles-morphing-shader

前言 通過著色器如何實現粒子之間動態切換 一、代碼 script.js import * as THREE from three import { OrbitControls } from three/addons/controls/OrbitControls.js import { GLTFLoader } from three/addons/loaders/GLTFLoader.js import { DRACOLoader } from three/a…

【PostgreSQL數據分析實戰:從數據清洗到可視化全流程】附錄-D. 擴展插件列表(PostGIS/PostgREST等)

&#x1f449; 點擊關注不迷路 &#x1f449; 點擊關注不迷路 &#x1f449; 點擊關注不迷路 文章大綱 附錄D. PostgreSQL擴展插件速查表一、插件分類速查表二、核心插件詳解三、安裝與配置指南四、應用場景模板五、版本兼容性說明六、維護與優化建議七、官方資源與工具八、附錄…

【Linux】馮諾依曼體系結構和操作系統的理解

目錄 馮諾依曼體系結構一個例子來深入理解 初識操作系統操作系統的作用設計操作系統的目的操作系統之上和之下分別有啥 管理的精髓&#xff0c;先描述&#xff0c;再組織 馮諾依曼體系結構 我們知道&#xff0c;計算機這個東西發明出來就是幫助人們快速解決問題的。那如果我們想…

kotlin @JvmStatic注解的作用和使用場景

1. JvmStatic 的作用 JvmStatic 是 Kotlin 提供的一個注解&#xff0c;用于在 JVM 上將伴生對象&#xff08;companion object&#xff09;中的方法或屬性暴露為 Java 靜態方法或字段。 作用對象&#xff1a;只能用在 companion object 中的函數或屬性。效果&#xff1a; 在 …

Redis實現-優惠卷秒殺(基礎版本)

(一)全局唯一ID 一、全局ID生成器 可以看到在優惠卷訂單表中的主鍵id并沒有設置Auto increment自增長 假如未來訂單量達到數億單&#xff0c;單表無法保存如此多數據&#xff0c;就需要對其進行分表存儲(分布式)。假如每張表都采用自增長&#xff0c;各自從1開始自增&#xf…

c++STL——哈希表封裝:實現高效unordered_map與unordered_set

文章目錄 用哈希表封裝unordered_map和unordered_set改進底層框架迭代器實現實現思路迭代器框架迭代器重載operator哈希表中獲取迭代器位置 哈希表的默認成員函數修改后的哈希表的代碼封裝至上層容器 用哈希表封裝unordered_map和unordered_set 在前面我們已經學過如何實現哈希…

虹科應用 | 探索PCAN卡與醫療機器人的革命性結合

隨著醫療技術的不斷進步&#xff0c;醫療機器人在提高手術精度、減少感染風險以及提升患者護理質量方面發揮著越來越重要的作用。醫療機器人的精確操作依賴于穩定且高效的數據通信系統&#xff0c;虹科提供的PCAN四通道mini PCIe轉CAN FD卡&#xff0c;正是為了滿足這一需求而設…

Yolov8的詳解與實戰-深度學習目標檢測

Yolov8的詳解與實戰- 文章目錄 摘要 模型詳解 C2F模塊 Loss head部分 模型實戰 訓練COCO數據集 下載數據集 COCO轉yolo格式數據集&#xff08;適用V4&#xff0c;V5&#xff0c;V6&#xff0c;V7&#xff0c;V8&#xff09; 配置yolov8環境 訓練 測試 訓練自定義數據集 Labelme…

scons user 3.1.2

前言 感謝您抽出時間閱讀有關 SCons 的內容。SCons 是一款下一代軟件構建工具&#xff0c;或者稱為 make 工具&#xff0c;即一種用于構建軟件&#xff08;或其他文件&#xff09;并在底層輸入文件發生更改時使已構建的軟件保持最新狀態的軟件實用程序。 SCons 最顯著的特點是…

Java的多線程筆記

創建一個線程的方法有多種&#xff0c;比如可以繼承Thread類或者實現Runnable接口&#xff0c;結論是實現Runnable接口比前者更加優越。 二者代碼對比 Java 不支持多繼承&#xff0c;如果你繼承了 Thread 類&#xff0c;就不能再繼承其他類&#xff0c;實現 Runnable 接口后&am…

PDF Base64格式字符串轉換為PDF文件臨時文件

需求描述&#xff1a; 在對接電子病歷系統與河北CA&#xff0c;進行免密文件簽章的時候&#xff0c;兩者系統入參不同&#xff0c;前者是pdf文件&#xff0c;base64格式&#xff1b;后者要求File類型的PDF文件。 在業務中間層開發時&#xff0c;則需要接收EMR側提供的base64格式…

代碼隨想錄訓練營第二十三天| 572.另一顆樹的子樹 104.二叉樹的最大深度 559.N叉樹的最大深度 111.二叉樹的最小深度

572.另一顆樹的子樹&#xff1a; 狀態&#xff1a;已做出 思路&#xff1a; 這道題目當時第一時間不是想到利用100.相同的樹思路來解決&#xff0c;而是先想到了使用kmp&#xff0c;不過這個題目官方題解確實是有kmp解法的&#xff0c;我使用的暴力解法&#xff0c;kmp的大致思…

【RabbitMq C++】消息隊列組件

RabbitMq 消息隊列組件 1. RabbitMq介紹2. 安裝RabbitMQ3. 安裝 RabbitMQ 的 C客戶端庫4. AMQP-CPP 庫的簡單使用4.1 使用4.1.1 TCP 模式4.1.2 擴展模式 4.2 常用類與接口介紹4.2.1 Channel4.3.2 ev 5. RabbitMQ樣例編寫5.1 發布消息5.2 訂閱消息 1. RabbitMq介紹 RabbitMq - …

鴻蒙NEXT開發動畫案例8

1.創建空白項目 2.Page文件夾下面新建Spin.ets文件&#xff0c;代碼如下&#xff1a; /*** SpinKit動畫組件 (重構版)* author: CSDN-鴻蒙布道師* since: 2025/05/14*/interface AnimationGroup {indexes: number[];delay: number; }ComponentV2 export struct SpinEight {Re…