最长回文字串Manacher算法学习

Posted on 2013-05-29 21:11  Lugh  阅读(163)  评论(0)    收藏  举报

这篇文章很好http://blog.sina.com.cn/s/blog_70811e1a01014esn.html

我的代码:

 1 #include<cstdlib>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5
 6 using namespace std;
 7
 8 char st[100010],s[100010];
 9 int rad[100010];
10 int mxn = 0,k,ans;
11
12 int main()
13 {
14     scanf("%s",st);
15     int len = strlen(st);
16     for (int i = 0; i < len; ++i)
17     {
18         s[(i<<1)+1] = st[i];
19         s[(i<<1)+2] = '#';
20     }
21     len = len << 1;
22     s[0] = '?';
23     for (int i = 1; i <= len;)
24     {
25         while (s[i-mxn-1] == s[i+mxn+1]) mxn++;
26         rad[i] = mxn;
27         for (k = 1; k <= mxn && rad[i-k]!=rad[i]-k; ++k)
28             rad[i+k] = min(rad[i-k],rad[i]-k);
29         i += k;
30         mxn = max(mxn-k,0);
31     }
32     for (int i = 1; i <= len; ++i)
33         if (i % 2) ans = max(ans,((rad[i]>>1)<<1)+1);
34         else ans = max(ans,((rad[i]+1)>>1)<<1);
35     for (int i = 1; i <= len; ++i)
36         printf("%c ",s[i]);
37     puts("");
38     for (int i = 1; i <= len; ++i)
39         printf("%d ",rad[i]);
40     puts("");
41     printf("%d\n",ans);
42     return 0;
43 }
View Code

其实很简单,就是将当前的点作为“回文中点”将其后面回文中的字符的作为中点的长度,通过对称求出来,因为前面的回文长度已经全部求出来了。因为每个点的回文长度只求了一次,所以复杂度为O(n)。