1. 程式人生 > >manacher演算法詳解+模板 P3805

manacher演算法詳解+模板 P3805

  首先我們知道迴文子串的判定和長度的奇偶性是有關係的,由於迴文分為偶迴文(比如 bccb)和奇迴文(比如 bcacb),而在處理奇偶問題上會比較繁瑣,所以這裡我們使用一個技巧,在字元間插入一個字元(前提這個字元未出現在串裡),常用的是"$""#"。舉個例子:s="abbahopxpo",轉換為newS="$#a#b#b#a#h#o#p#x#p#o#\0"(這裡在串首、尾加的字元"$"和"\0";只是設定邊界,為了防止越界,而且顯然不影響迴文子串,下面會有說明),如此,s 裡起初有一個偶迴文abba和一個奇迴文opxpo,被轉換為"#a#b#b#a#"和"#o#p#x#p#o#",長度都轉換成了奇數。

  證明經過上述操作迴文串的長度必為奇數:

    若原迴文串的長度為奇數n(原串 aaa),首尾間共有偶數n-1個空位被加上"#",加上首前和尾後各1個"#"(新串 #a#a#a#),可見新的長度為2n+1,顯然是奇數;

若原迴文串的長度為偶數n(原串 aa),首尾間共有奇數n-1個空位被加上"#",加上首前和尾後各1個"#"(新串 #a#a#),可見新的長度也為2n+1,顯然是奇數。得證。

  我們定義一個輔助陣列int p[]p[i]表示以news[i]為中心的最長迴文的半徑,例如

  易得P[i]-1即以i為中心的在原串中的迴文子串的長度:例如P[5]=5,則4就是以5這個位置為中心在原串中的最長迴文子串的長度(abba),為什麼這是對的呢?因為我們知道P[i]*2-1為新串中以i為中心的最長迴文子串的長度,設該回文子串原長為n,則由上面的證明可知新串的長度=2n+1=P[i]*2-1,移項化簡得n=P[i]-1。

  於是重點來了:我們如何快速的求出P[]陣列。這時就要用到DP的思想了,我們一般會想到這樣求解p[i],先初始化p[i]=1,再以news[i]為中心判斷兩邊是否相等,相等就p[i]++。這就是普通的思維,但是我們想想,能否避免重複操作讓p[i]的初始化不是 1,讓它更大點,看下圖:

  設定兩個變數,mx 和 id 。
  mx 代表以news[id]為中心的最長迴文最右邊界,也就是mx=id+p[id]。

  假設我們現在求p[i],也就是以news[i]為中心的最長迴文半徑,如果i<mx,如上圖,那麼

  if(i<mx) p[i] = min(p[id*2-i] , mx-i);

      

  else p[i] = 1;

 怎麼理解呢?我們看圖,因為mx是以id為中心的最長迴文半徑,若當前的i比mx要小,說明以i為中心的最長迴文子串的一部分已經出現在以id為中心的迴文子串中了,注意圖中下面標註的兩條短黑線,因為我們是線性dp,j點一定被訪問過且P[j]被處理過,而j與i關於id對稱(i+j=2*id),所以j=id*2-i,由於迴文串的對稱性,以i為中心的最長迴文子串中的半徑最小值一定是p[j]和mx-i中的最小值; 而若i>mx,就只能將p[i]賦為1來更新了。(感覺解釋了和沒解釋一樣啊,由於博主表述能力較差,我們不如舉例)

  就比如一個迴文子串:"#a#a#a#a#a#",我們以中間的a位置為id,所以id=6,mx=12。假設目前訪問到了i=8的位置,則與其對稱的j=2*6-8=4,而p[4]在訪問8之前已經處理,p[4]=4,mx-i=4,所以取最小值4,將p[8]初始值賦為4。因為很容易看出在當前已經可以確定的是以8為中心的最長迴文串的半徑至少為4(#a#a#a#),當然有可能更大,我們之後判斷news[i+P[i]]==news[i-P[i]]是否成立,若成立就p[i]++。

  講的好心累啊,我學manacher時完全自學,也沒有什麼解釋,完全是靠自己看懂的,還是得自己結合圖和程式碼理解啊,先發一波核心程式碼。

int manacher()
{
    int len=init();
    int ans=-N,id,mx=0;
    for(int i=1;i<len;i++)
    {
        if(i<mx)p[i]=min(p[id*2-i],mx-i);
        else p[i]=1;
        while(news[i-p[i]]==news[i+p[i]])p[i]++;
        if(mx<i+p[i])id=i,mx=i+p[i];
        ans=max(ans,p[i]-1);
    }
    return ans;
}

  再發兩種情況的圖片自行理解一番:

  這是初值p[i]=p[id*2-i]的圖:這裡寫圖片描述

相關推薦

manacher演算法+模板 P3805

  首先我們知道迴文子串的判定和長度的奇偶性是有關係的,由於迴文分為偶迴文(比如 bccb)和奇迴文(比如 bcacb),而在處理奇偶問題上會比較繁瑣,所以這裡我們使用一個技巧,在字元間插入一個字元(前提這個字元未出現在串裡),常用的是"$""#"。舉個例子:s="abbahopxpo",轉換為newS=

hihocoder 1032 最長迴文子串 (Manacher演算法 +模板)

時間限制:1000ms 單點時限:1000ms 記憶體限制:64MB 描述    小Hi和小Ho是一對好朋友,出生在資訊化社會的他們對程式設計產生了莫大的興趣,他們約定好互相幫助,在程式設計的

二分圖最大權值匹配 KM演算法 模板 KM演算法+模板

KM演算法詳解+模板  大佬講的太好了!!!太好了!!!  http://www.cnblogs.com/wenruo/p/5264235.html KM演算法用來求二分圖最大權完美匹配。 本文配合該博文服用更佳:趣寫算法系列之--匈牙利演算法 &nbs

KM演算法+模板

KM演算法用來求二分圖最大權完美匹配。 本文沒有給出KM演算法的原理,只是模擬了一遍演算法的過程。另,博主水平較差,發現問題歡迎指出,謝謝!!!! 現在有N男N女,有些男生和女生之間互相有好感,我們將其好感程度定義為好感度,我們希望把他們兩兩配對,並且最後希望好感度和最大。 怎麼選擇

KM演算法+模板(二分圖最大權值匹配)

KM演算法用來求二分圖最大權完美匹配。 本文沒有給出KM演算法的原理,只是模擬了一遍演算法的過程。另,博主水平較差,發現問題歡迎指出,謝謝!!!! 現在有N男N女,有些男生和女生之間互相有好感,我們將其好感程度定義為好感度,我們希望把他們兩兩配對,並且最後希

KM演算法+模板(轉)

KM演算法用來求二分圖最大權完美匹配。 本文配合該博文服用更佳:趣寫算法系列之–匈牙利演算法 現在有N男N女,男生和女生每兩個人之間有好感度,我們希望把他們兩兩配對,並且最後希望好感度和最大。 怎麼選擇最優的配對方法呢? 首先,每個妹子會有一

Floyd(弗洛伊德)演算法 +模板

弗洛伊德演算法介紹 和Dijkstra演算法一樣,弗洛伊德(Floyd)演算法也是一種用於尋找給定的加權圖中頂點間最短路徑的演算法。該演算法名稱以創始人之一、1978年圖靈獎獲得者、斯坦福大學計算機科學系教授羅伯特·弗洛伊德命名。 基本思想 通過Floyd計算

Manacher演算法

Manacher演算法 演算法總結第三彈 manacher演算法,前面講了兩個字串相演算法——kmp和拓展kmp,這次來還是來總結一個字串演算法,manacher演算法,我習慣叫他 “馬拉車”演算法。 相對於前面介紹的兩個演算法,Manacher演算法的應用範圍要狹窄得多,但是它的思想和拓展k

[轉] Manacher演算法

const int maxn=1000010; char str[maxn];//原字串 char tmp[maxn<<1];//轉換後的字串 int Len[maxn<<1]; //轉換原始串 int INIT(char *st) { int i,len=s

最長迴文子串-Manacher演算法()

定義: 迴文串:一個字串, 逆置之後,與原串相同; 迴文子串: 一個字串的子串(連續),是迴文串.則該子串為整個字串的一個迴文子串. 最長迴文子串:一個字串中最長的迴文子串.

第k短路 演算法(圖解)與模板(A* 演算法

老規矩,先放模板,有時間放圖解 #include <map> #include <queue> #include <cstdlib> #include <cma

網路最大流-ISAP演算法模板

ISAP演算法 ISAP(Improved Shortest Augumenting Path)演算法是改進版的SAP演算法,如果對效率要求很高的時候,可以用該演算法。 (1)概述:演算法基於這樣的一個事實:每次增廣之後,任意結點到匯點(在殘餘網路中)的最短距離都不會

【HDU 2255】【KM演算法模板題+KM演算法】 奔小康賺大錢

描述: 奔小康賺大錢 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 7453    Accepted S

演算法】揹包模板或模型

01揹包 有N 件物品和一個容量為V 的揹包。放入第i 件物品耗費的空間 是vi,得到的價值是wi。求解將哪些物品裝入揹包可使價值總和最大。 根據題意,我們便可以設f[i][j]為已經裝了i件物品且最大容量為j得最大價值. 此時,我們就可以列舉i和j進行動

網路流-Dinic演算法模板

Dinic演算法詳解: 我們已經學過了求最大網路流的EK演算法,EK演算法的思想是每次用bfs找增廣路,然後利用記錄的路徑回退到原點的過程更新網路。 (1)Dinic演算法的思路是這樣的:每次都不停地用BFS來構造“層次圖”,然後用“阻塞流”來增廣。這裡我特

【learning】 多項式求逆元+模板

n) 意義 詳解 需要 一個 求逆 ont time 前置 概述 多項式求逆元是一個非常重要的知識點,許多多項式操作都需要用到該算法,包括多項式取模,除法,開跟,求ln,求exp,快速冪。用快速傅裏葉變換和倍增法可以在$O(n log n)$的時間復雜度下求出一個$n$次

php openssl_sign() 語法+RSA公私鑰加密解密,非對稱加密演算法

其實有時候覺得寫部落格好煩,就個函式就開篇部落格。很小的意見事情而已,知道的人看來多取一舉,或者說沒什麼必要,浪費時間,不知道的人就會很鬱悶。技術就是這樣的,懂的人覺得真的很簡單啊,不知道的人真的好難。。。 一般在跟第三方介面對接資料的時候,為了保證很多都使用的RSA簽名,沒性趣瞭解的同學只需要

Show, attend and tell演算法及原始碼

mark一下,感謝作者分享! https://blog.csdn.net/shenxiaolu1984/article/details/51493673 原論文:https://arxiv.org/pdf/1502.03044v2.pdf 原始碼:https://github.c

資料分析學習之不得不知的八大演算法

學習資料分析的朋友們都知道,演算法是不可或缺的,或者說演算法在一定程度上可以更好的量化的一個人的學習能力和水平,本文感謝科多大資料的馮老師,由他整理了經典的八大演算法,相關的資料希望能幫助大家瞭解。 演算法一:快速排序法 快速排序是由東尼 · 霍爾所發展的一種排序演算法。在平均狀況下,排序

程式設計思想 - 五大常用演算法

https://www.cnblogs.com/brucemengbm/p/6875340.html https://blog.csdn.net/changyuanchn/article/details/51476281 https://www.cnblogs.com/chuninggao/p/