Manacher算法是求回文串最高效的算法,能在线性时间内求出以每一个字符为中心的最长回文串。
首先,我们都能想出$O(N^2)$求出每一个字符为中心的最长回文串的算法。那么我们考虑这样一种情况。
如果一个回文串内包含了回文串。那么是否可以减少重复的计算。
比如
abaaba 这个字符串,要求他的最长回文串,首先我们应区分开奇数串和偶数串,考虑给每个字符中间加上一个之前从来没有出现过的字符,通常采用‘#’。
那么上面那个字符串就变成了
#a#b#a#a#b#a#
这时候就免除了对奇数串还是偶数串的分类讨论。即所有的回文串都是奇数串。
再思考这样一个情况,如果我们已经求出了第六个字符的最长回文串和第三个字符的最长回文串,那么第9个字符串的最长回文串长度显然等于第三个字符的最长回文串长度。即如果一个字符串是回文的,那么这个字符串倒转过来显然仍然是回文串。这就使Manacher算法变得很高效。
代码实现:
namespace solution{ void manacher(){ if(!((s[0]>='a'&&s[0]<='z')||(s[0]>='A'&&s[0]<='Z')))exit(0); LEN=strlen(s); t[0]='!'; up(i,1,LEN*2){ t[i]='#'; t[i+1]=s[i/2]; i++; } t[2*LEN+1]='#'; t[2*LEN+2]='$'; LEN=2*LEN+1; rightt=ans=pos=0; up(i,1,LEN){ if(rightt>i)len[i]=min(rightt-i,len[2*pos-i]); else len[i]=1; while(t[i-len[i]]==t[i+len[i]])len[i]++; if(len[i]+i>rightt){ rightt=len[i]+i; pos=i; } ans=max(ans,len[i]); } printf("%d\n",ans-1); } }
首先把字符串转变,同时在最后一个字符处加上不同于所有字符的字符,防止越界。然后下面就是manacher算法的流程。不再多说。