最长回文子串之Manacher算法

Hihocoder 1032为例。

manacher算法:

设一个数组p,p[i]表示以第i个字符为中心的最大半径,最大的p[i]就是最长的回文子串了。

不过这样要用两个循环,时间复杂度是(n*n)。

 1 int solve(){
 2     int len = strlen(str), ans = 0;
 3     for(int i = 0; i < len; i ++){
 4         for(int j = 0; i-j>=0 && i+j < len; j++){
 5             if(str[i-j] != str[i+j])break;
 6             if(j*2+1 > ans) ans=j*2+1;
 7         }
 8         for(int j = 0; i-j >= 0 && i+j+1 < len; j ++){
 9             if(str[i-j] != str[i+j+1])break;
10             if(2*j+2 > ans) ans = 2*j+2;
11         }
12     }
13     return ans;
14 }

而manacher算法可以快速的求p[i],设i之前的最大值为p[id]+id,那么p[id]+id大于i时,p[i] = min(p[2*id-i],p[id]+id-i),否则p[i] = 1,具体的证明过程可以参考这里

AC代码:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 using namespace std;
 5 const int MAX = 1e6+10;
 6 char str[MAX<<1];
 7 int p[MAX<<1];
 8 int solve(){
 9     int ans = 0, id = 0, len = strlen(str);
10     for(int i = len; i >= 0; i --){
11         str[i+i+2] = str[i];
12         str[i+i+1] = '#';
13     }
14     str[0] = '*';
15     for(int i = 2; i<2*len+1; i ++){
16         if(p[id] + id > i) p[i] = min(p[2*id-i],p[id]+id-i);
17         else p[i] = 1;
18         while(str[i-p[i]] == str[i+p[i]])++p[i];
19         if(p[id] + id < p[i]+i) id = i;
20         if(ans < p[i]) ans = p[i];
21     }
22     return ans-1;
23 }
24 int main(){
25     int n;
26     scanf("%d",&n);
27     while(n--){
28         scanf("%s",str);
29         printf("%d\n",solve());
30         memset(str,0,sizeof(str));
31         memset(p,0,sizeof(p));
32     }
33     return 0;
34 }

 

posted @ 2017-07-06 18:57  starry_sky  阅读(194)  评论(0编辑  收藏  举报