1.做用:Manacher算法又名馬拉車算法,用來求一個字符串中最長迴文子串的長度。ios
2.複雜度分析:時間複雜度爲O(n)。算法
1.僞代碼:假設str爲待判斷的字符串,len[ i ]數組存放以該 str[ i ] 字符爲中心的最長迴文子串的長度,mid爲當前最長迴文子串的中點,mx爲當前最長迴文子串的右邊界,那麼對當前位置 i 有以下僞代碼:(此時以知道前 i - 1個字符中最長迴文子串的長度以及以每一個字符爲中心的最長迴文串的長度)數組
2.算法思路:爲什麼能按照這樣步奏執行算法呢?spa
2.1 i < mx : code
首先,若是 i < mx,說明字符 str[ i ] 在以mid爲中心的迴文串中,那麼其與以 str[ j ]( i 關於 mid 的對稱位置)爲中心的最長迴文串有關。而以 str[ j ]字符爲中心的最長迴文串有三種可能:blog
咱們能夠證實第一種與第二種狀況下,以 str[ i ] 爲中心的最長迴文串的長度爲len[ j ] 或 mx - i。[ 註釋1 ]而第三種狀況下,以str[ i ] 爲中心的迴文串長度卻可能大於len[ j ],故須要走僞代碼中的第3步來更新len[ i ] 。字符串
2.2 i >= mx :string
而若是i >= mx 狀況下,說明以 i 爲中心的最長迴文串沒法從以前獲得的len[ 1 ~ i -1]中得知,只能先令len[ i ] = 1,再分別向兩邊拓展,判斷迴文長度了,故走僞代碼中二、3步。io
註釋1:證實第1、第二中狀況下以str[ i ]爲中心的最長迴文串的長度爲len[ j ] 或 mx - i。模板
//Manacher #include<iostream> #include<cstring> #include<cstdio> using namespace std; const int MAXN = 1e5; char str[MAXN]; char tmp[2*MAXN]; int len[2*MAXN]; int Manacher(char str[]){ tmp[0] = '$'; tmp[1] = '#'; int str_len = strlen(str); for(int i = 1;i <= str_len;i++){ tmp[2*i] = str[i-1]; tmp[2*i+1] = '#'; } tmp[2*str_len+2] = '\0'; //cout << tmp << endl; int mx = 0; int maxlen = -1; int mid; for(int i = 1; tmp[i]; i++){ if(i < mx) len[i] = min(len[2*mid-i],mx-i); else len[i] = 1; while(tmp[i-len[i]] == tmp[i+len[i]]) len[i]++; if(len[i]+i > mx){ mx = len[i]+i; mid = i; } maxlen = max(maxlen,len[i]-1); } return maxlen; } int main(){ scanf("%s",str); cout << Manacher(str); return 0; }