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

hdoj 5371 Hotaru's problem

时间:2015-08-12 18:48:55      阅读:138      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5371

这道题用到了Manacher算法,首先简单介绍一下Manacher算法:

----------------------------------------------------------------------------------------------

【转】http://blog.csdn.net/yzl_rex/article/details/7908259

一个专门针对回文子串的算法,其时间复杂度为O(n)

求回文串时需要判断其奇偶性,也就是求aba 和abba 的算法略有差距。然而,这个算法做了一个简单的处理,

很巧妙地把奇数长度回文串与偶数长度回文串统一考虑,也就是在每个相邻的字符之间插入一个分隔符,

串的首尾也要加,当然这个分隔符不能再原串中出现,一般可以用‘#’或者‘$’等字符。

这样一来,原来的奇数长度回文串还是奇数长度,偶数长度的也变成以‘#’为中心奇数回文串了。

接下来就是算法的中心思想,用一个辅助数组P 记录以每个字符为中心的最长回文半径,

也就是P[i]记录以Str[i]字符为中心的最长回文串半径。P[i]最小为1,此时回文串为Str[i]本身。

核心代码:

1 if (maxid > i){
2              p[i] = min(p[2*id - i], maxid - i);
3          }

技术分享

技术分享

-----------------------------------------------------------------------------------------------

再回到本题,因为所给的数列为非负整数,所以用-1作为间隔,利用Manacher算法求出各点的最长回文,

然后因为 abbaab 可以理解为 abba 和 baab 两个回文串,所以在第一个回文串的末尾往回找,

如果回文串的长度大于两点之间的距离,且大于sum,则更新sum。

在遍历过程中进行简化,易知回文串必然是偶数个的,所以只遍历-1的点就可以了。

 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int MAXN = 200050;
 6     int str[MAXN];
 7     int p[MAXN];
 8     int N;
 9 int main(){
10     int T;
11     int TT = 0;
12     int mx, pi;
13     int _max;
14     int j;
15     scanf("%d",&T);
16     while(T--){
17         memset(p,0,sizeof(p));
18         memset(str,0,sizeof(str));
19         str[0] = -100;
20         str[1] = -1;
21         scanf("%d",&N);
22         getchar();
23         N = N * 2 + 1;
24         for(int i = 2; i < N; i++){
25             if( i % 2 == 0)
26                 scanf("%d",&str[i]);
27             else str[i] = -1;
28         }
29         str[N++] = -1;
30         int lgt = N;
31         mx = 0; pi = 1;
32         for( int i = 1; i < lgt; i = i + 1){
33             if(str[i] == -1){
34                 if( i < mx)
35                     p[i] = min(p[2*pi-i],mx-i);
36                 else
37                     p[i] = 1;
38                 while( str[i-p[i]] == str[i+p[i]])
39                     p[i]++;
40                 if( p[i]+i > mx ){
41                     pi = i;
42                     mx = p[i]+i;
43                 }
44             }
45         }
46         _max = 0;
47         for(int i = 1; i < lgt; i = i + 1){
48             if( p[i] > _max && str[i] == -1){
49                 while( j > lgt) j -= 2;
50                 for( j = i + p[i] - 1; j - i + 1 > _max; j -= 2 ){
51                     if( p[j] >= j - i + 1)
52                         _max = j - i + 1;
53                 }
54             }
55         }
56         printf("Case #%d: %d\n",++TT,(_max-1)/2*3);
57     }
58 }

 

hdoj 5371 Hotaru's problem

标签:

原文地址:http://www.cnblogs.com/blueprintf/p/4725066.html

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