传说中的马拉车算法233
(先吐槽,manacher我一直觉得打成manachar比较对2333)
manachar的第一步(很神奇的一步),就是把原串每个字符中间再加上一个原串没有出现的字符,为什么这样搞呢?
自己可以画一个图看一下:2333其实加上直接,原来的回文长度就都是奇数了。
然后有2个变量,mx和id,表示id位置的回文长度最大,到了mx位。还有一个p[]数组,表示每个位置的回文长度。最后的答案就是max{p[i]}-1(不要问为什么)
那么这些东西是怎么work(用高大上的词汇)的呢?
http://www.cnblogs.com/biyeymyhjob/archive/2012/10/04/2711527.html
大概的意思就是利用了回文的性质,用 i 关于 id 的对称点 j 来更新 i 的答案,当然是在 i<mx 的前提下。那么用对称点跟新过来的答案就是min(p[j],mx-i)
然后剩下不知道的再暴力匹配就好。
因为这个东西的mx就正好跑完一个串,所以复杂度肯定是O(n)的啊233
裸题:
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 #include <iostream> 6 #define LL long long 7 using namespace std; 8 9 const int maxn=233333; 10 11 int len[maxn<<1]; 12 char a[maxn]; 13 14 int manachar(char *p) 15 { 16 char s[maxn<<1]; 17 int n=strlen(p),l=0; 18 s[l++]='@'; s[l++]='#'; 19 for (int i=0; i<n; i++) 20 { 21 s[l++]=p[i]; 22 s[l++]='#'; 23 } 24 s[l++]='~'; s[l]=0; 25 int mx=0,pos=0,ans=0; 26 for (int i=1; i<l; i++) 27 { 28 if (mx>i) len[i]=min(len[2*pos-i],mx-i); else len[i]=1; 29 while (s[i+len[i]]==s[i-len[i]]) len[i]++; 30 ans=max(ans,len[i]); 31 if (len[i]+i>mx) mx=len[i]+i,pos=i; 32 } 33 return ans-1; 34 } 35 36 int main() 37 { 38 while (scanf("%s",a)!=EOF) printf("%d ",manachar(a)); 39 }