【字符串】馬拉車(Manacher)算法

本篇文章參考:比較易懂的 Manacher(馬拉車)算法配圖詳解

馬拉車算法可以求出一個字符串中的最長回文子串,時間復雜度 O ( n ) O(n) O(n)

因為字符串長度的奇偶性,回文子串的中心可能是一個字符,也可能是兩個字符中間的位置,所以為了解決這個問題,我們在每兩個字符之間加一個 # ,開頭再加一個 $ 防止越界

比如說:

abcd 變成 $#a#b#c#d#

接下來是后文需要的一些定義:

  • c 表示當前已經計算過的最靠右的回文子串的中心點的下標
  • m 表示以 c 為中心的回文子串的右端點下標
  • p[i] 表示以 s[i] 為中心的回文子串的半徑(包括自身)

對于以每一個位置為中心點的時候單獨計算,復雜度很大,馬拉車可以對其進行很好地優化

目前的難點就是怎么計算 p[i]

在這里插入圖片描述

看上面這張圖,我們當前需要計算 p[i],我們可以去找 i 關于 c 的對稱點(記為 j),因為我們是從左往右計算的,所以 p[j] 已經計算過了,如果以 j 為中心的回文子串在以 c 為中心的回文子串中時,我們可以直接把 p[j] 賦給 p[i]

當然會出現一些特殊情況:

  • 如果 p[j] + i > m,如下圖所示,以 c 為中心的回文子串包不住,我們就更新 p[i] = m - i (先只更新確定的部分)
    在這里插入圖片描述
  • 如果 i 在 m 右側,如下圖所示,更新 p[i] = 1
    在這里插入圖片描述

上面的情況都只能得到半成品的 p[i],所以需要對 s[i] 進行中心擴展,得到最終的 p[i]

如果最終的 p[i] + i > m 此時已經有比以 c 為中心的回文子串更靠右的回文子串了,就把 c = i m = p[i] + 1

求完 p[i] 后算法結束

求最長回文子串板子

string Manacher(string s)
{int sl = s.size(); // 原字符串長度if (sl == 0 || sl == 1) return s;// 構建新串string ns = "$#";for (int i = 0; i < sl; i ++ ){ns += s[i];ns += '#';}int len = ns.size();int c = 0; // 最靠右的回文子串的中心點下標int m = 0; // 最靠右的回文子串的右端點下標int pos = 0; // 最長回文子串的中心點int maxlen = 0; // 最長回文子串的半徑(不包括中心點)(新字符串中)vector<int> p(len); // p[i]表示以i為中心點的回文子串的半徑(包括i)for (int i = 1; i < len; i ++ ){if (i < m) p[i] = min(p[c - (i - c)], m - i + 1); // c-(i-c)是i關于c的對稱點 當前情況表示i在目前最靠右側的回文子串中else p[i] = 1 + (ns[i] != '#'); // 當前不是#的話 其兩側就是# 所以半徑可以加1if (i - p[i] >= 0 && i + p[i] < ns.size())while (ns[i - p[i]] == ns[i + p[i]]) p[i] ++ ; // 對半成品的i位置進行中心擴散if (i + p[i] - 1 > m) // 產生了比以c為中心時更靠右的回文子串{c = i;m = i + p[i] - 1;}if (p[i] - 1 > maxlen) // 更新最長回文子串{maxlen = p[i] - 1;pos = i;}}string ans = "";char tmp;for (int i = 0; i < 2 * maxlen * 1; i ++ ) // 遍歷最長字串的每個位置 得出原字符串中的最長字串{tmp = ns[pos - (maxlen - 1) + i];if (tmp != '#') ans += tmp;}return ans;
}

求最長前綴or后綴回文子串板子

string Manacher(string s)
{int sl = s.size(); // 原字符串長度if (sl == 0 || sl == 1) return s;// 構建新串string ns = "$#";for (int i = 0; i < sl; i ++ ){ns += s[i];ns += '#';}int len = ns.size();int c = 0; // 最靠右的回文子串的中心點下標int m = 0; // 最靠右的回文子串的右端點下標int pos = 0; // 最長回文子串的中心點int maxlen = 0; // 最長回文子串的半徑(不包括中心點)(新字符串中)// int flag; // 可以用這個標記是前綴回文子串最長還是后綴回文子串最長vector<int> p(len); // p[i]表示以i為中心點的回文子串的半徑(包括i)for (int i = 1; i < len; i ++ ){if (i < m) p[i] = min(p[c - (i - c)], m - i + 1); // c-(i-c)是i關于c的對稱點 當前情況表示i在目前最靠右側的回文子串中else p[i] = 1 + (ns[i] != '#'); // 當前不是#的話 其兩側就是# 所以半徑可以加1if (i - p[i] >= 0 && i + p[i] < ns.size())while (ns[i - p[i]] == ns[i + p[i]]) p[i] ++ ; // 對半成品的i位置進行中心擴散if (i + p[i] - 1 > m) // 產生了比以c為中心時更靠右的回文子串{c = i;m = i + p[i] - 1;}if (p[i] == i && maxlen < p[i]) // 最長前綴回文子串{maxlen = p[i] - 1;pos = i;// flag = 1;}if (p[i] + i == len && maxlen < p[i]) // 最長后綴回文子串{maxlen = p[i] - 1;pos = i;// flag = 2;}}string ans = "";char tmp;for (int i = 0; i < 2 * maxlen * 1; i ++ ) // 遍歷最長字串的每個位置 得出原字符串中的最長字串{tmp = ns[pos - (maxlen - 1) + i];if (tmp != '#') ans += tmp;}return ans;
}

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

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

相關文章

uniapp聊天記錄本地存儲(詳細易懂)

目錄 目錄 1、通過websocket拿取數據 2、獲取聊天數據 3、聊天信息存儲 、更新 4、讀取聊天記錄 5、發送信息&#xff0c;信息獲取 6、最終效果 1.聊天信息的存儲格式 2、樣式效果 寫聊天項目&#xff0c;使用到了本地存儲。需要把聊天信息保存在本地&#xff0c;實時獲…

GPT對話知識庫——ARM-Cortex架構分為哪幾個系列?每個系列有幾種工作模式?各種工作模式之間的定義和區別?每種架構不同的特點和應用需求?

提問模型&#xff1a;GPT-4-TURBO-PREVIEW 提問時間&#xff1a;2024.03.02 1&#xff0c;問&#xff1a; Cortex-M系列有幾種工作模式 1&#xff0c;答&#xff1a; Cortex-M系列微控制器是ARM公司開發的一類低功耗、高性能的32位微處理器&#xff0c;廣泛應用于嵌入式系統中…

Centos7使用man查找命令時,報錯No manual entry for xxxx

Centos7使用man查找命令時&#xff0c;報錯No manual entry for xxxx 在Linux中使用man指令查找指令信息時&#xff0c;報No manual entry for xxxx。 比如使用man指令查找sleep3號手冊時&#xff0c;出現以下錯誤&#xff1a; 這是由于沒有安裝man-pages這個rpm包導致的&#…

掌握基本排序算法:冒泡、選擇、插入和快速排序

在計算機科學的世界里&#xff0c;排序是一項基本而重要的操作。無論是數據庫管理、搜索引擎&#xff0c;還是日常編程&#xff0c;高效的排序算法都是提高性能的關鍵。本文將介紹四種基本的排序算法&#xff1a;冒泡排序、選擇排序、插入排序和快速排序&#xff0c;并探討它們…

從0開始學習NEON(1)

1、前言 在上個博客中對NEON有了基礎的了解&#xff0c;本文將針對一個圖像下采樣的例子對NEON進行學習。 學習鏈接:CPU優化技術 - NEON 開發進階 上文鏈接:https://blog.csdn.net/weixin_42108183/article/details/136412104 2、第一個例子 現在有一張圖片&#xff0c;需…

獲取 Windows 通知中心彈窗通知內容(含工具漢化)

目錄 前言 技術原理概述 測試代碼和程序下載連接 本文出處鏈接&#xff1a;https://blog.csdn.net/qq_59075481/article/details/136440280。 前言 從 Windows 8.1 開始&#xff0c;Windows 通知現在以 Toast 而非 Balloon 形式顯示&#xff08; Bollon 通知其實現在是應用…

在ubuntu上安裝hadoop完分布式

準備工作 Xshell安裝包 Xftp7安裝包 虛擬機安裝包 Ubuntu鏡像源文件 Hadoop包 Java包 一、安裝虛擬機 創建ubuntu系統 完成之后會彈出一個新的窗口 跑完之后會重啟一下 按住首先用ctrlaltf3進入命令界面&#xff0c;輸入root&#xff0c;密碼登錄管理員賬號 按Esc 然后輸入 …

數據結構常用的字符串函數(中英雙釋)

頭文件&#xff1a;string.h 1.strchr const char * strchr ( const char * str, int character ); Locate first occurrence of character in string str C string. character Character to be located. Return Value A pointer to the first occurrence of character in s…

適用于恢復iOS數據的 10 款免費 iPhone 恢復軟件

現在&#xff0c;您可以獲得的 iPhone 的存儲容量比大多數人的筆記本電腦和臺式電腦的存儲容量還要大。雖然能夠存儲數千張高分辨率照片和視頻文件、安裝數百個應用程序并隨身攜帶大量音樂庫以供離線收聽固然很棒&#xff0c;但在一個地方擁有如此多的數據可能會帶來毀滅性的后…

2.2_5 調度算法

文章目錄 2.2_5 調度算法一、適用于早期的批處理系統&#xff08;一&#xff09;先來先服務&#xff08;FCFS&#xff0c;First Come First Serve&#xff09;&#xff08;二&#xff09;短作業優先&#xff08;SJF&#xff0c;Shortest Job First&#xff09;&#xff08;三&a…

SpringMVC總結

SpringMVC SpringMVC是隸屬于Spring框架的一部分&#xff0c;主要是用來進行Web開發&#xff0c;是對Servlet進行了封裝。 對于SpringMVC我們主要學習如下內容: SpringMVC簡介 請求與響應 REST風格 SSM整合(注解版) 攔截器 SpringMVC是處理Web層/表現層的框架&#xff…

易語言源代碼5000例

僅供學習研究交流使用 加群下載

探索MyBatis-Plus的高階用法

引言 MyBatis-Plus 是 MyBatis 的增強工具包&#xff0c;提供了許多方便快捷的功能來簡化開發&#xff0c;提高效率。除了基本的 CRUD 操作外&#xff0c;MyBatis-Plus 還提供了一些高級功能&#xff0c;本文將探討 MyBatis-Plus 的高階用法&#xff0c;幫助開發者更好地利用該…

Linux服務器搭建超簡易跳板機連接阿里云服務器

簡介 想要規范內部連接阿里云云服務器的方式&#xff0c;但是最近懶病犯了&#xff0c;先搞一個簡易式的跳板機過渡一下&#xff0c;順便在出一個教程&#xff0c;其他以后再說&#xff01; 配置方法 創建密鑰 登錄阿里云&#xff0c;找到云服務器ECS控制臺&#xff0c;點擊…

【小白友好】LeetCode 打家劫舍 III

https://leetcode.cn/problems/house-robber-iii/description/ 前言 建議還是先看看動態規劃的基礎題再看這個。動態規劃是不刷題&#xff0c;自己100%想不出來的。 基礎題&#xff1a; 23 小白想法 現在我們想遍歷的數據結構不是數組了&#xff0c;而是一顆樹。在樹上的d…

C++遞推

統計每個月兔子的總數 #include<bits/stdc.h> using namespace std; int n,sum0; void f(int); int main() {int a[1000];cin>>n;a[1]1;a[2]2;for(int i3;i<1000;i){a[i]a[i-1]a[i-2];}cout<<a[n];return 0; } void f(int n){}猴子吃桃子 #include<b…

2024年華為OD機試真題-電腦病毒感染-Python-OD統一考試(C卷)

題目描述: 一個局域網內有很多臺電腦,分別標注為0 - N-1的數字。相連接的電腦距離不一樣,所以感染時間不一樣,感染時間用t表示。 其中網絡內一個電腦被病毒感染,其感染網絡內所有的電腦需要最少需要多長時間。如果最后有電腦不會感染,則返回-1 給定一個數組times表示一個…

在Spring Boot中如何實現異常處理?

在Spring Boot中&#xff0c;異常處理可以通過幾種方式實現&#xff0c;以提高應用程序的健壯性和用戶體驗。這些方法包括使用ControllerAdvice注解、ExceptionHandler注解、實現ErrorController接口等。下面是一些實現Spring Boot異常處理的常用方法&#xff1a; 1. 使用Cont…

Git實戰(2)

git work flow ------------------------------------------------------- ---------------------------------------------------------------- 場景問題及處理 問題1&#xff1a;最近提交了 a,b,c,d記錄&#xff0c;想把b記錄刪掉其他提交記錄保留&#xff1a; git reset …

【C++ 編程指南】

C 編程指南 ■ C環境安裝■ C 基本語法■ 預定義宏■ # 和 ## 運算符■ C 引用■ C 命名空間■ 定義命名空間■ using 指令■ 嵌套的命名空間 ■ String類■ 類■ 類的static靜態成員 ■ C 繼承■ 繼承類型 public、protected 或 private■ 訪問控制和繼承■ 多繼承■ 數據抽象…