算法 --- 字符串

字符串

字符串算法題目主要處理文本的查找、匹配、比較、變換和統計問題,其核心特點是輸入數據為字符序列,解題關鍵在于利用其連續性、前綴性、字典序等特性,并常借助哈希、自動機、指針滑動、動態規劃等技巧高效處理。


詳細分類型與適用場景

當一道題的輸入是一個或多個字符串時,你就應該考慮使用字符串算法。以下是主要的題目類型和適用場景:

1. 基礎操作與模擬
  • 特點:直接考察對字符串的索引、遍歷、拼接、反轉等基本操作。

  • 常見題型:字符串反轉、判斷回文串、實現基本的字符串轉換(如?atoi)、Z字形變換等。

  • 適用場景:問題描述本身就像是在指導你一步步操作字符串。

2. 匹配與查找問題

這是字符串問題的核心領域。

  • 特點:在一個主串(文本)中查找一個或多個模式串是否存在及出現的位置。

  • 常見算法

    • 暴力匹配:簡單但低效,適用于小規模數據。

    • KMP算法:高效的單模式串匹配,利用“部分匹配表”避免回溯。

    • Rabin-Karp算法:利用滾動哈希進行多模式串匹配的預處理。

    • 字典樹(Trie):快速檢索字符串集合中是否存在某個前綴或整個字符串。

    • AC自動機字典樹 + KMP?的思想,用于多模式串匹配的終極武器(如敏感詞過濾)。

  • 適用場景:問題中出現“查找子串”、“所有出現位置”、“是否包含某些單詞”等關鍵詞。

3. 子串與子序列問題
  • 特點:不要求連續(子序列)或要求連續(子串)的序列問題,常求最大、最小、最長、最短等。

  • 常見題型

    • 最長回文子串:使用中心擴散法或Manacher算法。

    • 最長公共子串/子序列(LCS):經典動態規劃問題。

    • 最長不含重復字符的子串:使用滑動窗口(雙指針)的代表性問題。

    • 最短編輯距離:另一個經典的動態規劃問題,衡量兩個字符串的相似度。

  • 適用場景:問題要求找到一個滿足特定條件的“序列”,且這個序列源自原字符串。

4. 計數與統計問題
  • 特點:統計字符串中字符、子串、模式出現的頻率、數量或分布。

  • 常見題型:統計字母出現次數、統計“優美子串”的數目、不同子串的個數等。

  • 適用場景:問題中出現“有多少種”、“出現次數”、“頻率最高”等統計性詞匯。常結合哈希表來記錄頻率。

5. 分割與組合問題
  • 特點:將字符串按一定規則進行分割,或者由多個部分組合成一個新字符串。

  • 常見題型:單詞拆分、回文分割、恢復IP地址等。

  • 適用場景:問題要求將字符串切割成若干段,每段需要滿足特定條件。這類問題通常使用回溯法(DFS)?或動態規劃來解決。

6. 表達式 parsing 與計算
  • 特點:處理具有特定語法結構的字符串,如數學表達式、JSON、XML等。

  • 常見題型:基本計算器(實現加減乘除括號)、逆波蘭表達式求值、解析HTML標簽等。

  • 適用場景:輸入字符串具有明確的遞歸或嵌套結構。解決方案通常是使用遞歸下降等解析方法。

7. 字符串排序與字典序問題
  • 特點:利用字符串的字典序特性進行排序或比較。

  • 常見題型:拼接所有字符串使字典序最小、最長快樂前綴、后綴數組等。

  • 適用場景:問題要求比較字符串的“大小”或按特定順序排列字符串。

總結

當你看到問題的輸入是字符串,并且問題目標涉及查找、匹配、比較、變換、計數、分割這幾種操作時,它就是一個字符串算法題。解決它們的關鍵是選擇合適的數據結構(哈希表、Trie、棧)和算法思想(滑動窗口、動態規劃、回溯、自動機)。

題目練習

14. 最長公共前綴 - 力扣(LeetCode)

解法:

算法思路:

解法一(兩兩比較):

我們可以先找出前兩個的最長公共前綴,然后拿這個最長公共前綴依次與后面的字符串比較,這樣就可以找出所有字符串的最長公共前綴

class Solution {
public:string longestCommonPrefix(vector<string>& strs) {string ret = strs[0];for(int i = 1; i < strs.size(); ++i)ret = findCommon(ret, strs[i]);return ret;}string findCommon(string& s1, string& s2){int i = 0;while(i < min(s1.size(), s2.size()) && s1[i] == s2[i]) ++i;return s1.substr(0, i);}
};

解法二(統一比較):

題目要求多個字符串的公共前綴,我們可以逐位比較這些字符串,哪一位出現了不同,就在哪一位截止

class Solution {
public:string longestCommonPrefix(vector<string>& strs) {for(int i = 0; i < strs[0].size(); ++i){char tmp = strs[0][i];for(int j = 1; j < strs.size(); ++j){if(i == strs[j].size() || tmp != strs[j][i]) return strs[0].substr(0, i);}}return strs[0];}
};

5. 最長回文子串 - 力扣(LeetCode)

解法(中心擴散):

算法思路:

枚舉每一個可能的子串非常費時,有沒有比較簡單一點的方法呢?

對于一個子串而言,如果它是回文串,并且長度大于 2,那么將它首尾的兩個字母去除之后,它仍然是個回文串。如此這樣去除,一直除到長度小于等于 2 時呢?長度為 1 的,自身與自身就構成回文;而長度為 2 的,就要判斷這兩個字符是否相等了。

從這個性質可以反推出來,從回文串的中心開始,往左讀和往右讀也是一樣的那么,是否可以枚舉回文串的中心呢?

從中心向兩邊擴展,如果兩邊的字母相同,我們就可以繼續擴展;如果不同,我們就停止擴展。這樣只需要一層 for 循環,我們就可以完成先前兩層 for 循環的工作量。

class Solution {
public:string longestPalindrome(string s) {int begin = 0, len = 0, n = s.size();for(int i = 0; i < n; ++i){int left = i, right = i;while(left >= 0 && right < n && s[left] == s[right]){left--;right++;}if(right - left - 1 > len){begin = left + 1;len = right - left - 1;}left = i, right = i + 1;while(left >= 0 && right < n && s[left] == s[right]){left--;right++;}if(right - left - 1 > len){begin = left + 1;len = right - left - 1;}}return s.substr(begin, len);}
};

67. 二進制求和 - 力扣(LeetCode)

解法(模擬十進制的大數相加的過程):

算法思路:

模擬十進制中我們列豎式計算兩個數之和的過程。但是這里是二進制的求和,我們不是逢十進一,而是逢二進一

class Solution {
public:string addBinary(string a, string b) {string ret;int cur1 = a.size() - 1, cur2 = b.size() - 1, t = 0;while(cur1 >= 0 || cur2 >= 0 || t){if(cur1 >= 0) t += a[cur1--] - '0';if(cur2 >= 0) t += b[cur2--] - '0';ret += t % 2 + '0';t /= 2;}reverse(ret.begin(), ret.end());return ret;}
};

43. 字符串相乘 - 力扣(LeetCode)

解法(無進位相乘然后相加,最后處理進位):

算法思路:

整體思路就是模擬我們小學列豎式計算兩個數相乘的過程。但是為了我們書寫代碼的方便性,我們選擇一種優化版本的,就是在計算兩數相乘的時候,先不考慮進位,等到所有結果計算完畢之后,再去考慮進位。如下圖:

class Solution {
public:string multiply(string num1, string num2) {int m = num1.size(), n = num2.size();reverse(num1.begin(), num1.end());reverse(num2.begin(), num2.end());vector<int> tmp(m + n - 1);for(int i = 0; i < m; ++i){for(int j = 0; j < n; ++j){tmp[i + j] += (num1[i] - '0') * (num2[j] - '0');}}int cur = 0, t = 0;string ret;while(cur < m + n - 1 || t){if(cur < m + n - 1) t += tmp[cur++];ret += t % 10 + '0';t /= 10;}while(ret.size() > 1 && ret.back() == '0') ret.pop_back();reverse(ret.begin(), ret.end());return ret;}
};

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

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

相關文章

SpringBoot中 Gzip 壓縮的兩種開啟方式:GeoJSON 瘦身實戰

目錄 前言 一、GZIP壓縮知識簡介 1、什么是Gzip 2、Gzip特點 3、Gzip在GIS方面的應用 二、SpringBoot中開啟Gzip的方式 1、在SpringBoot中開啟Gzip的知識簡介 2、SpringBoot中GeoJSON的實例 三、全局開啟Gzip實現 1、實現原理 2、實現效果 四、局部約定配置 1、實現…

PPTist+cpolar:開源演示文稿的遠程創作方案

文章目錄前言【視頻教程】1. 本地安裝PPTist2. PPTist 使用介紹3. 安裝Cpolar內網穿透4. 配置公網地址6. 配置固定公網地址前言 PPTist作為開源在線演示文稿工具&#xff0c;提供媲美PowerPoint的核心功能&#xff0c;支持多頁面編輯、圖表插入、音視頻嵌入和動畫效果設置。特…

服務注冊/服務發現-Eureka

目的&#xff1a;解決微服務在調用遠程服務時URL寫死的問題注冊中心服務提供者&#xff08;Server&#xff09;&#xff1a;一次業務中&#xff0c;被其他微服務調用的服務&#xff0c;也就是提供接口給其他微服務。服務消費者&#xff08;Client&#xff09;:一次業務中&#…

cuda stream

基本概念 cuda stream表示GPU的一個操作隊列&#xff0c;操作在隊列中按照一定的順序執行&#xff0c;也可以向流中添加一定的操作如核函數的啟動、內存的復制、事件的啟動和結束等 一個流中的不同操作有著嚴格的順序&#xff0c;但是不同流之間沒有任何限制 cuda stream中排隊…

數據結構:完全二叉樹

完全二叉樹 定義&#xff1a; 按層序遍歷&#xff08;從上到下&#xff0c;從左到右&#xff09;填充節點。 除了最后一層外&#xff0c;其余各層必須全滿。 最后一層的節點必須 連續靠左。 完全二叉樹不一定是滿二叉樹。 滿二叉樹 (Full Binary Tree)&#xff1a;每個節點都有…

【Java初學基礎】?Object()頂級父類與它的重要方法equals()

object類常見方法/*** native 方法&#xff0c;用于返回當前運行時對象的 Class 對象&#xff0c;使用了 final 關鍵字修飾&#xff0c;故不允許子類重寫。*/ public final native Class<?> getClass() /*** native 方法&#xff0c;用于返回對象的哈希碼&#xff0c;主…

用深度學習(LSTM)實現時間序列預測:從數據到閉環預測全解析

用深度學習&#xff08;LSTM&#xff09;實現時間序列預測&#xff1a;從數據到閉環預測全解析 時間序列預測是工業、金融、環境等領域的核心需求——小到預測設備溫度波動&#xff0c;大到預測股價走勢&#xff0c;都需要從歷史數據中挖掘時序規律。長短期記憶網絡&#xff08…

gpu-z功能介紹,安裝與使用方法

GPU-Z 功能介紹、安裝與使用方法 一、核心功能 硬件信息檢測 識別顯卡型號、制造商、核心架構&#xff08;如NVIDIA Ada Lovelace、AMD RDNA 3&#xff09;、制造工藝&#xff08;如5nm、7nm&#xff09;。顯示顯存類型&#xff08;GDDR6X、HBM2e&#xff09;、容量、帶寬及顯…

數據搬家后如何處理舊 iPhone

每年&#xff0c;蘋果都會推出新款 iPhone&#xff0c;激發了人們升級到 iPhone 17、iPhone 17 Pro、iPhone 17 Pro Max 或 iPhone Air 等新機型的熱情。但在獲得新 iPhone 之前&#xff0c;有一件重要的事情要做&#xff1a;將數據從舊 iPhone 轉移到新設備。雖然許多用戶都能…

Java關鍵字深度解析(上)

這是一份全面的Java關鍵字實戰指南 目錄 1.數據類型關鍵字:內存布局與性能優化 1.1 基礎類型的內存密碼 byte-內存的極簡主義者 int-Java世界的萬能鑰匙 long - 時間與ID的守護者 1.2 引用類型的架構設計 String-不是關鍵字但勝于關鍵字 2.訪問修飾符:企業級權限控制 …

C語言深度解析:指針數組與數組指針的區別與應用

目錄 1 引言&#xff1a;從名字理解本質區別 2 指針數組&#xff1a;靈活管理多個指針 2.1 基本概念與聲明方式 2.2 內存布局與特性 2.3 典型應用場景&#xff1a;字符串數組與多維度數據管理 2.3.1 靜態分配示例&#xff1a;字符串數組 2.3.2 動態分配示例&#xff1a;…

Node.js 高級應用:負載均衡與流量限制

在當今高并發的網絡應用環境中&#xff0c;如何有效地分配服務器資源并保護系統免受惡意攻擊是開發者必須面對的重要問題。Node.js 作為一款廣受歡迎的服務器端 JavaScript 運行時環境&#xff0c;提供了豐富的工具和模塊來應對這些挑戰。本文將深入探討如何在 Node.js 中實現負…

信任鏈驗證流程

信任鏈驗證流程 (The Chain of Trust)整個過程就像一場嚴格的接力賽&#xff0c;每一棒都必須從可信的上一位手中接過接力棒&#xff08;信任&#xff09;&#xff0c;驗證無誤后&#xff0c;再跑自己的那段路&#xff0c;并把信任傳遞給下一棒現在&#xff0c;我們來詳細解讀圖…

黃昏時刻復古膠片風格人像風光攝影后期Lr調色教程,手機濾鏡PS+Lightroom預設下載!

調色教程這套 黃昏時刻復古膠片風格人像風光攝影后期 Lr 調色方案&#xff0c;以落日余暉為核心色彩元素&#xff0c;加入復古膠片質感&#xff0c;讓畫面充滿溫暖與懷舊氛圍。整體色調偏向橙紅與青綠的互補對比&#xff0c;天空的夕陽光影與人像膚色相互映襯&#xff0c;既有膠…

硬件驅動——I.MX6ULL裸機啟動(3)(按鍵設置及中斷設置

重點&#xff1a;1.GIC&#xff1a;&#xff08;Generic Interrupt Controller&#xff09;通用中斷控制器&#xff0c;是ARM架構中用于管理中斷的核心模塊&#xff0c;主要用于現代多核處理器系統。它負責接收&#xff0c;分發并分發中斷請求&#xff0c;減輕CPU負擔&#x…

用deepseek對GPU服務器進行壓力測試

利用 DeepSeek 模型對 GPU 服務器進行壓力測試&#xff0c;核心思路是通過模擬高負載的模型推理 / 微調任務&#xff0c;驗證 GPU 服務器在計算、顯存、網絡等維度的承載能力&#xff0c;同時觀察穩定性與性能瓶頸。以下是具體的測試方案&#xff0c;涵蓋測試環境準備、核心測試…

ARM(7)IMX6ULL 按鍵控制(輪詢 + 中斷)優化工程

一、硬件介紹1. 開關功能定義共 3 個開關&#xff08;兩紅一黃&#xff09;&#xff0c;功能分工明確&#xff1a;中間開關&#xff1a;復位按鈕左邊開關&#xff1a;低功耗按鈕右邊開關&#xff1a;用戶獨立控制的試驗按鍵&#xff08;核心控制對象&#xff09;2. 核心電平邏輯…

【QT隨筆】什么是Qt元對象系統?Qt元對象系統的核心機制與應用實踐

【QT隨筆】什么是Qt元對象系統&#xff1f;Qt元對象系統的核心機制與應用實踐 之所以寫下這篇文章&#xff0c;是因為前段時間自己面試的時候被問到了&#xff01;因此想借此分享一波&#xff01;&#xff01;&#xff01;本文主要詳細解釋Qt元對象系統的概念、作用及實現機制…

從技術視角解析加密貨幣/虛擬貨幣/穩定幣的設計與演進

隨著加密貨幣行情的持續走高&#xff0c;除了資產價值&#xff0c;我想試著從底層程序設計與架構角度解析比特幣、以太坊、穩定幣以及新興公鏈的核心技術方案。作者在2018年設計實施了基于區塊鏈技術的金融項目&#xff0c;并榮獲了國家課題進步獎&#xff0c;對加密貨幣及場景…

[MySQL]Order By:排序的藝術

[MySQL]Order By&#xff1a;排序的藝術 1. 簡介 在數據庫管理中&#xff0c;數據的排序是一項至關重要的操作。MySQL 的 ORDER BY 子句為我們提供了強大而靈活的功能&#xff0c;用于對查詢結果進行排序。無論是按照字母順序排列名稱&#xff0c;還是根據日期或數值進行升序…