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; }