码迷,mamicode.com
首页 > 其他好文 > 详细

Manacher 最长回文串问题

时间:2014-09-25 00:56:57      阅读:282      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   io   ar   for   div   sp   问题   

  有人问你,一个字符串中最长的回文字串是谁?

  作为一个 2B 青年, 一年前的我会这样回答:暴力枚举每个字串,判断合法与否?

  ╮(╯▽╰)╭ 就是没什么戏。。。。

  后来,在机房的一个大牛的介绍下,我知道了 Manacher 算法。

  。。。。。。。。。。。。。。。。。。。。。。。。。。。。

  其实 Manacher 和 KMP 是非常之像的。

  令 rad[i] 表示以 第 i 个字符为中心的回文字串的半径长度。

  那么我们考虑一下当前最远拓展到 j 编号为 rad[k],那么我们当前要计算的 rad[i] 有如下几种情况:

  i 关于 k 对称的字符为 t = k + k - i. 那么如果 i + rad[t] < j 那么 rad[i] = rad[t]

                      若 i + rad[t] >= j我们必须 暴力拓展 直到失配为止

  这样子的话,复杂度是 O(n) 的。比暴力好了很多。

  我们看一下代码:

    

 1 #include<cstdlib>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define maxn 310100
 6 using namespace std;
 7 char s[maxn],Ma[maxn];
 8 int rad[maxn],Max,L,kase;
 9 void manacher(char s[],int L)
10 {
11     memset(rad,0,sizeof(rad));
12     Max = 0;
13     int len = 0;
14     Ma[len++] = #;
15     for(int i=0;i<L;++i){
16         Ma[len++] = s[i];
17         Ma[len++] = #;
18     }
19     int i,j,k;
20     for(int i=1,j=0;i<len;i+=k){
21         while(Ma[i-j-1] == Ma[i+j+1] && i-j-1>=0 && i+j+1<len)
22             j++;
23         rad[i] = j;
24         Max = max(rad[i],Max);
25         for(k=1;k<=rad[i] && rad[i]<rad[i-k]+k;++k)
26             rad[i+k] = min(rad[i-k],rad[i]-k),
27             Max = max(Max,rad[i+k]);
28         j = max(j-k,0);
29     }
30 }
31 int main()
32 {
33     freopen("manacher.in","r",stdin);
34     freopen("manacher.out","w",stdout);
35     while(scanf("%s",s)!=EOF){
36         if(s[0] == E)break;
37         L = strlen(s);
38         manacher(s,L);
39         printf("Case %d: %d\n",++kase,Max);
40     }
41     return 0;
42 }        

 

Manacher 最长回文串问题

标签:style   blog   color   io   ar   for   div   sp   问题   

原文地址:http://www.cnblogs.com/RHX-LMY/p/3991586.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!